Copybara import of the project: - c6f2abbb52eb834b28739d90dbee78b549aa4312 Initial commit by Eclipse Webmaster team <webmaster@eclipse.org> - f160a13c1253b6f06205c6082573b115a68a312c Initial contribution by Dmitry Kornilov <dmitry.kornilov@oracle.com> - 63536332cd9e5ded826a8d0af133999c51e3ec61 Facebook resource files updated (#81) by David Král <4483705+Verdent@users.noreply.github.com> - d5bded4af804870d46e3bbe4ae8de132258d23a1 Travis CI build. (#83) by Tomáš Kraus <tomas.kraus@oracle.com> - f49271c2959703edae66229dd146f9e6dbfb9f91 Yasson Issue #89 - Pretty formatting (#87) by David Král <4483705+Verdent@users.noreply.github.com> - c0632f03ddaf8f6592152b4f3e8083cf284564a4 Merge pull request #89 from Tomas-Kraus/master by Roman Grigoriadi <bravehorsie@gmail.com> - 6306ef2039497c96919f5207eedf9bede7d3bd07 add NOTICE and CONTRIBUTING files (#93) by Lukas Jungmann <lukas.jungmann@oracle.com> - 9892c0658f9d55b819d39039a364df37d1d60202 set version to 1.1.3-SNAPSHOT (#94) by Lukas Jungmann <lukas.jungmann@oracle.com> - dca81ea88de8248ff06907ce36920055c8517302 Merge pull request #98 from Tomas-Kraus/master by Werner Keil <werner.keil@gmx.net> - cb041e37abdb426bd850fe732c7270ae8d0be40b Added .gitignore file (#112) by Cousjava <jonathan.coustick@payara.fish> - f1639f44c5d61d5e123b1edf948af4da5a833006 'jakarta' groupId fix (#113) by Dmitry Kornilov <maiden168@gmail.com> - 052502d5f8cef0b9f1f631ab83138c9c470c4beb add service provider configuration for classpath mode (#1... by Lukas Jungmann <lukas.jungmann@oracle.com> - 3ca0db0beb0eea791f1524b40ecb4d730181fd59 fix bundle resource packaging (#119) by Lukas Jungmann <lukas.jungmann@oracle.com> - e82316a124e524e92ed14e1ae65aa56111a48bc7 fix for regression #104 (#127) by Lukas Jungmann <lukas.jungmann@oracle.com> - 01ee02ac803cbf5c78bbb39959b6b4c48f69a1a5 Jdk11 preparation, jakarta uptake, osgi and docs fixes (#... by Lukas Jungmann <lukas.jungmann@oracle.com> - 543b496a910356c03f0b919b80cd36902a837f91 fix parsing of invalid json with jsonvalue (#130) by Lukas Jungmann <lukas.jungmann@oracle.com> - 3b142eec04a61f92961afdbea5f3403a064148cd version in master should be 1.2 (#131) by Lukas Jungmann <lukas.jungmann@oracle.com> - 9ccc20a01ddbb8e70a74b4a9fe40eb7348c94551 Fixes #135: impl artifactId should be 'jakarta.json' (#1... by Lukas Jungmann <lukas.jungmann@oracle.com> - 0fd6e98f62257e855b09a7348ab12438456d19f0 Use correct version of common annotations (#139) by Lukas Jungmann <lukas.jungmann@oracle.com> - 817010b5f66e965f19726a045b20adcb3ad76a1a Parent updated to 1.0.5. (#144) by Tomáš Kraus <tomas.kraus@oracle.com> - 77e8d242b56a2875d9a8ed4dd1d8c697834af7fe Update README.md by Dmitry Kornilov <dmitry.kornilov@oracle.com> - decc9d77d55191cb45559ea202ec5d9b63871533 Update README.md by Dmitry Kornilov <dmitry.kornilov@oracle.com> - 5b44888209c53c0b9026c25e5537b99d77d86e92 Merge pull request #161 from leadpony/fix_jsonpointer by Werner Keil <werner.keil@gmx.net> - d9eff6686bb6cd9242b9dc0b3d4c83de7bd7fd26 Merge pull request #162 from leadpony/fix_javadoc11 by Werner Keil <werner.keil@gmx.net> - 89f768a53d7131d74d83db0d608d42f008113518 Boilerplate spec and Jakarta EE 8 related updates (#184) by Dmitry Kornilov <dmitry.kornilov@oracle.com> - f54831312f1850182e21c6184c4734120373fe8f Update README.txt by Dmitry Kornilov <dmitry.kornilov@oracle.com> - 487e4a22228fdd326fc77699c762f9e73e8ea034 fix doc status in dev/release version (#192) by Lukas Jungmann <lukas.jungmann@oracle.com> - 1f18b590f8c3aa17390b4866cc51d23f8349f992 Update README.md by Dmitry Kornilov <dmitry.kornilov@oracle.com> - 41d3e8e87046ae52381ad24337e5b2ebe40036be add speclicense, remove JSON-P occurences, update readme by Lukas Jungmann <lukas.jungmann@oracle.com> - fa68b5d83ed397dc9172a51d20a9524d7ea9b38b Set Trusty for the Travis to support OracleJDK8 by Jan Supol <jan.supol@oracle.com> - c8daac3b2a11ad7c7cbbdd7c56fcd919b0a224bf Fixed documentation error for Operation.REPLACE. (#172) by Jesper de Jong <jesperdj@users.noreply.github.com> - 8f748778e1ffd71be1f0b1f0e5ca8b5de48f5fcf Implemented hashCode() with caching for JsonArrayImpl, Js... by Jean-Philippe Gariépy <gawix@yahoo.com> - 4ec63ceadd19e8565896d3c21ed15d832cb90fb0 Fixes #146: Avoid using exceptions for flow control in Js... by Jason Hinch <46059987+jhinch-at-atlassian-com@users.noreply.github.com> - d4d0bf449c3ee7d127bc4e79243d81f9c0708956 fix cp holder (#201) by Lukas Jungmann <lukas.jungmann@oracle.com> - 5735bb62715578633d5721bf583b837506bbec73 Update overview.html (#208) by Dmitry Kornilov <dmitry.kornilov@oracle.com> - 5cb006b440dfcd5108e27f984882d6bcde64e394 Merge pull request #214 from Cousjava/jakarta-rename by Werner Keil <werner.keil@gmx.net> - 7e261a696a361b3b16141ee8e7363da6c347179e Bug 169 : Operation path encoding as required by RFC6901 ... by dylanBehetre <dylan.behetre@capgemini.com> - ee6e2e6e5dbde08b15c24d59821bcc536ec46fd3 Fixed jabadoc build. (#217) by Tomáš Kraus <tomas.kraus@oracle.com> - 3174ac4077a1e2f14832ca79737db30d43ee387d Configured copyright and spotbugs plugin. (#222) by Tomáš Kraus <tomas.kraus@oracle.com> - eb28d33785ee278615294011027d4b8cf6614e36 Module java.json renamed to jakarta.json. (#223) by Tomáš Kraus <tomas.kraus@oracle.com> - 2360cabee260cb146769066b364a30d745efe175 Parent pom updated to 1.0.6 by Tomas Kraus <Tomas.Kraus@oracle.com> - 4e7977906d358730c2bc12522e8fad050a759b2a jakarta.json.jar will contain api and impl (#228) by jbescos <jorge.bescos.gascon@oracle.com> - dd38d6e9d0d101c7b3d0a5e8960331ef0fa9a628 Fix warning in API (#229) by jbescos <jorge.bescos.gascon@oracle.com> - 1d622ceb928407894488a4b1140266863dbd5566 Parent is not relatively reachable for this project (#231) by Piotrek Żygieło <pzygielo@users.noreply.github.com> - 57c8b5215d79995e77f9ff907844c4e65bd5545f Remove duplicated plugin, set up just above (#230) by Piotrek Żygieło <pzygielo@users.noreply.github.com> - 7186d73ef8050cbf58a380bc78aa5cb16b26f720 Merge pull request #224 from lmsurpre/master by Nathan Mittlestat <nmittles@us.ibm.com> - 3994ab23a5d122c0199565d5301080682f00222a Upgrade jakarta ws rs api to 3.0.0-M1 (#236) by Dmitry Kornilov <dmitry.kornilov@oracle.com> - b73a070c3b5cb6f09b405e933de857efdb1c1436 avoid costly service lookups from the default implementat... by Lukas Jungmann <lukas.jungmann@oracle.com> - 4d30288c1dca29b327076de12f06f007b0fbae5f #238: Update CONTRIBUTING.md for Specification Project's ... by Lukas Jungmann <lukas.jungmann@oracle.com> - 8a924b48fba919286a23ab828d1480e844d6dcaf Jsonp tck (#232) by jbescos <jorge.bescos.gascon@oracle.com> - 400b3260ff74fce6d0494045378686ca64091930 clean up api project build,require jdk11 as the base for ... by Lukas Jungmann <lukas.jungmann@oracle.com> - db3113e9b8d66ee5038e4612e6c549f1f3699180 update travis by Lukas Jungmann <lukas.jungmann@oracle.com> - 3b374281753eb4a469137fa6d4664ceb99638b1c require jdk11 for the build, by Lukas Jungmann <lukas.jungmann@oracle.com> - faad4ecb78a78913c32bdb9b8e5d1ca8cfafc82d drop integration with jaxrs 1x by Lukas Jungmann <lukas.jungmann@oracle.com> - 15524e275d538bf1a6f00cf775121c44f55f59de Fix broken image in pdf spec, by Lukas Jungmann <lukas.jungmann@oracle.com> - 36e1b43507413c92eb8b3e43138173148a730464 Integrate json-api 2.0.0 by Lukas Jungmann <lukas.jungmann@oracle.com> - 5e834a30cec1f07d93a7971d7886e0716ef85520 change module name of the implementation to org.glassfish... by Lukas Jungmann <lukas.jungmann@oracle.com> - 68293e807cfd15a450189c7add17de2f272adbf9 Integrate jakarta.servlet-api 5.0.0-M1 by Lukas Jungmann <lukas.jungmann@oracle.com> - e24d3faab99a29177653557257516d4d941ab943 update samples, by Lukas Jungmann <lukas.jungmann@oracle.com> - aab9d6ed1a95f438a0d5c8fddcbca7903669c047 allow build on jdk14 by Lukas Jungmann <lukas.jungmann@oracle.com> - 5d7704d0573f2a107f9681d208bf3e9b490b084e #211: Handle Collections and Maps containing JsonValues by Lukas Jungmann <lukas.jungmann@oracle.com> - 44a6bd1f95e88388711cf2aee070ed8341f8f955 Signed-off-by: Lukas Jungmann <lukas.jungmann@oracle.com> by Lukas Jungmann <lukas.jungmann@oracle.com> - 47ccfe65287a7cf84f1666a1d445b23b85ef5b24 fix spec vendor in manifest by Lukas Jungmann <lukas.jungmann@oracle.com> - dcef07f088197eb7f44829a3ccf4f6a9b99d29ff Fix project readme (#255) by Lukas Jungmann <lukas.jungmann@oracle.com> - 6af0fad002efd25bfeda00f71c8c7aeeeb8a4f4a Update RI version of org.glassfish:jakarta.json to 2.0.0 by Eclipse JSON-P Bot <jsonp-bot@eclipse.org> - 0ddbbb642d0e8880a118aa4d4f6be4c249ca85e2 Update RI version of org.glassfish:jakarta.json to 2.0.1-... by Eclipse JSON-P Bot <jsonp-bot@eclipse.org> - abca44b7ab0d95f7aa5e994e79baef5cdcc8e000 Repare broken links from overview by Thibault Vallin <thibault.vallin@oracle.com> - 62c57bcdc78695d2fd7226791b23507ff933ae7a [api] bump project version, update build plugins by Lukas Jungmann <lukas.jungmann@oracle.com> - f0a26c5d83539ee624e9a30400af2198639747c3 Issue #240 - added support for "reject duplicate keys" co... by John T.E. Timm <johntimm@us.ibm.com> - 82f08a5d856634c77a6771b06ec05fb28bf61216 integrate latest dependencies, by Lukas Jungmann <lukas.jungmann@oracle.com> - dcf112f3992b2425f9397e428b8e16e00bca9272 fix cp headers by Lukas Jungmann <lukas.jungmann@oracle.com> - 888975fc13b93d7ad69e3572de965d02e8dcf91e Integrate jsonp-api 2.0.1 by Lukas Jungmann <lukas.jungmann@oracle.com> - 97a55d55c7506a98a4cc9ccdc256f5f0242f04f9 CP year fix by Maxim Nesen <maxim.nesen@oracle.com> - 73014364fac9e67f981720f233ed86ec05aaff47 CP year fix by Maxim Nesen <maxim.nesen@oracle.com> - 35ed2f330c6d4fa2b3d50b020b5e84a76366af80 Update RI version of org.glassfish:jakarta.json to 2.0.1 by Eclipse JSON-P Bot <jsonp-bot@eclipse.org> GitOrigin-RevId: 35ed2f330c6d4fa2b3d50b020b5e84a76366af80 Change-Id: If8677153dbbfdad97267f13ea4e9bf3eb4903964
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..998689f --- /dev/null +++ b/.gitignore
@@ -0,0 +1,26 @@ +# Maven noise +target/ + +# OSX noise +.DS_Store + +# IntelliJ Idea noise +.idea +*.iws +*.ipr +*.iml + +# Eclipse noise +.settings/ +.classpath +.project + +# NetBeans noise +nbproject/ + +# VS Code noise +.vscode/ + +# Java noise +*.class +*err_pid*.log
diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..54994b3 --- /dev/null +++ b/.travis.yml
@@ -0,0 +1,25 @@ +dist: bionic + +language: java + +jdk: + - openjdk11 + - openjdk14 + +cache: + directories: + - .autoconf + - $HOME/.m2 + +install: true + +script: + - cd api + - mvn -U -C -Pstaging,oss-release -Dnon.final=true -Dgpg.skip=true clean verify + - cd .. + - mvn -U -C -Pstaging,oss-release,all -Dnon.final=true -Dgpg.skip=true clean verify + - cd tck + - mvn -U clean install + - cd ../impl-tck + - mvn -U clean test +
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c4527fe --- /dev/null +++ b/CONTRIBUTING.md
@@ -0,0 +1,74 @@ +[//]: # " Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved. " +[//]: # " " +[//]: # " This program and the accompanying materials are made available under the " +[//]: # " terms of the Eclipse Public License v. 2.0, which is available at " +[//]: # " http://www.eclipse.org/legal/epl-2.0. " +[//]: # " " +[//]: # " This Source Code may also be made available under the following Secondary " +[//]: # " Licenses when the conditions for such availability set forth in the " +[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, " +[//]: # " version 2 with the GNU Classpath Exception, which is available at " +[//]: # " https://www.gnu.org/software/classpath/license.html. " +[//]: # " " +[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 " + +# Contributing to Jakarta JSON Processing + +Thanks for your interest in this project. + +## Project description + +Jakarta JSON Processing is a Java API to process (e.g. parse, generate, +transform and query) JSON documents. It produces and consumes JSON in a +streaming fashion (similar to StAX API for XML) and allows to build a Java +object model for JSON using API classes (similar to DOM API for XML). + +* https://projects.eclipse.org/projects/ee4j.jsonp + +## Developer resources + +Information regarding source code management, builds, coding standards, and +more. + +* https://projects.eclipse.org/projects/ee4j.jsonp/developer + +The project maintains the following source code repositories + +* https://github.com/eclipse-ee4j/jsonp + +## Eclipse Development Process + +This Eclipse Foundation open project is governed by the Eclipse Foundation +Development Process and operates under the terms of the Eclipse IP Policy. + +The Jakarta EE Specification Committee has adopted the Jakarta EE Specification +Process (JESP) in accordance with the Eclipse Foundation Specification Process +v1.2 (EFSP) to ensure that the specification process is complied with by all +Jakarta EE specification projects. + +* https://eclipse.org/projects/dev_process +* https://www.eclipse.org/org/documents/Eclipse_IP_Policy.pdf +* https://jakarta.ee/about/jesp/ +* https://www.eclipse.org/legal/efsp_non_assert.php + +## Eclipse Contributor Agreement + +Before your contribution can be accepted by the project team contributors must +electronically sign the Eclipse Contributor Agreement (ECA). + +* http://www.eclipse.org/legal/ECA.php + +Commits that are provided by non-committers must have a Signed-off-by field in +the footer indicating that the author is aware of the terms by which the +contribution has been provided to the project. The non-committer must +additionally have an Eclipse Foundation account and must have a signed Eclipse +Contributor Agreement (ECA) on file. + +For more information, please see the Eclipse Committer Handbook: +https://www.eclipse.org/projects/handbook/#resources-commit + +## Contact + +Contact the project developers via the project's "dev" list. + +* https://dev.eclipse.org/mailman/listinfo/jsonp-dev \ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..5de3d1b --- /dev/null +++ b/LICENSE.md
@@ -0,0 +1,637 @@ +# Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + + 1. DEFINITIONS + + "Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + + "Contributor" means any person or entity that Distributes the Program. + + "Licensed Patents" mean patent claims licensable by a Contributor which + are necessarily infringed by the use or sale of its Contribution alone + or when combined with the Program. + + "Program" means the Contributions Distributed in accordance with this + Agreement. + + "Recipient" means anyone who receives the Program under this Agreement + or any Secondary License (as applicable), including Contributors. + + "Derivative Works" shall mean any work, whether in Source Code or other + form, that is based on (or derived from) the Program and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. + + "Modified Works" shall mean any work in Source Code or other form that + results from an addition to, deletion from, or modification of the + contents of the Program, including, for purposes of clarity any new file + in Source Code form that contains any contents of the Program. Modified + Works shall not include works that contain only declarations, + interfaces, types, classes, structures, or files of the Program solely + in each case in order to link to, bind by name, or subclass the Program + or Modified Works thereof. + + "Distribute" means the acts of a) distributing or b) making available + in any manner that enables the transfer of a copy. + + "Source Code" means the form of a Program preferred for making + modifications, including but not limited to software source code, + documentation source, and configuration files. + + "Secondary License" means either the GNU General Public License, + Version 2.0, or any later versions of that license, including any + exceptions or additional permissions as identified by the initial + Contributor. + + 2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + + 3. REQUIREMENTS + + 3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + + 3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + + 3.3 Contributors may not remove or alter any copyright, patent, + trademark, attribution notices, disclaimers of warranty, or limitations + of liability ("notices") contained within the Program from any copy of + the Program which they Distribute, provided that Contributors may add + their own appropriate notices. + + 4. COMMERCIAL DISTRIBUTION + + Commercial distributors of software may accept certain responsibilities + with respect to end users, business partners and the like. While this + license is intended to facilitate the commercial use of the Program, + the Contributor who includes the Program in a commercial product + offering should do so in a manner which does not create potential + liability for other Contributors. Therefore, if a Contributor includes + the Program in a commercial product offering, such Contributor + ("Commercial Contributor") hereby agrees to defend and indemnify every + other Contributor ("Indemnified Contributor") against any losses, + damages and costs (collectively "Losses") arising from claims, lawsuits + and other legal actions brought by a third party against the Indemnified + Contributor to the extent caused by the acts or omissions of such + Commercial Contributor in connection with its distribution of the Program + in a commercial product offering. The obligations in this section do not + apply to any claims or Losses relating to any actual or alleged + intellectual property infringement. In order to qualify, an Indemnified + Contributor must: a) promptly notify the Commercial Contributor in + writing of such claim, and b) allow the Commercial Contributor to control, + and cooperate with the Commercial Contributor in, the defense and any + related settlement negotiations. The Indemnified Contributor may + participate in any such claim at its own expense. + + For example, a Contributor might include the Program in a commercial + product offering, Product X. That Contributor is then a Commercial + Contributor. If that Commercial Contributor then makes performance + claims, or offers warranties related to Product X, those performance + claims and warranties are such Commercial Contributor's responsibility + alone. Under this section, the Commercial Contributor would have to + defend claims against the other Contributors related to those performance + claims and warranties, and if a court requires any other Contributor to + pay any damages as a result, the Commercial Contributor must pay + those damages. + + 5. NO WARRANTY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT + PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR + IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF + TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR + PURPOSE. Each Recipient is solely responsible for determining the + appropriateness of using and distributing the Program and assumes all + risks associated with its exercise of rights under this Agreement, + including but not limited to the risks and costs of program errors, + compliance with applicable laws, damage to or loss of data, programs + or equipment, and unavailability or interruption of operations. + + 6. DISCLAIMER OF LIABILITY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT + PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS + SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST + PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE + EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + + 7. GENERAL + + If any provision of this Agreement is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this Agreement, and without further + action by the parties hereto, such provision shall be reformed to the + minimum extent necessary to make such provision valid and enforceable. + + If Recipient institutes patent litigation against any entity + (including a cross-claim or counterclaim in a lawsuit) alleging that the + Program itself (excluding combinations of the Program with other software + or hardware) infringes such Recipient's patent(s), then such Recipient's + rights granted under Section 2(b) shall terminate as of the date such + litigation is filed. + + All Recipient's rights under this Agreement shall terminate if it + fails to comply with any of the material terms or conditions of this + Agreement and does not cure such failure in a reasonable period of + time after becoming aware of such noncompliance. If all Recipient's + rights under this Agreement terminate, Recipient agrees to cease use + and distribution of the Program as soon as reasonably practicable. + However, Recipient's obligations under this Agreement and any licenses + granted by Recipient relating to the Program shall continue and survive. + + Everyone is permitted to copy and distribute copies of this Agreement, + but in order to avoid inconsistency the Agreement is copyrighted and + may only be modified in the following manner. The Agreement Steward + reserves the right to publish new versions (including revisions) of + this Agreement from time to time. No one other than the Agreement + Steward has the right to modify this Agreement. The Eclipse Foundation + is the initial Agreement Steward. The Eclipse Foundation may assign the + responsibility to serve as the Agreement Steward to a suitable separate + entity. Each new version of the Agreement will be given a distinguishing + version number. The Program (including Contributions) may always be + Distributed subject to the version of the Agreement under which it was + received. In addition, after a new version of the Agreement is published, + Contributor may elect to Distribute the Program (including its + Contributions) under the new version. + + Except as expressly stated in Sections 2(a) and 2(b) above, Recipient + receives no rights or licenses to the intellectual property of any + Contributor under this Agreement, whether expressly, by implication, + estoppel or otherwise. All rights in the Program not expressly granted + under this Agreement are reserved. Nothing in this Agreement is intended + to be enforceable by any entity that is not a Contributor or Recipient. + No third-party beneficiary rights are created under this Agreement. + + Exhibit A - Form of Secondary Licenses Notice + + "This Source Code may also be made available under the following + Secondary Licenses when the conditions for such availability set forth + in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), + version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. + +--- + +## The GNU General Public License (GPL) Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor + Boston, MA 02110-1335 + USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your freedom to + share and change it. By contrast, the GNU General Public License is + intended to guarantee your freedom to share and change free software--to + make sure the software is free for all its users. This General Public + License applies to most of the Free Software Foundation's software and + to any other program whose authors commit to using it. (Some other Free + Software Foundation software is covered by the GNU Library General + Public License instead.) You can apply it to your programs, too. + + When we speak of free software, we are referring to freedom, not price. + Our General Public Licenses are designed to make sure that you have the + freedom to distribute copies of free software (and charge for this + service if you wish), that you receive source code or can get it if you + want it, that you can change the software or use pieces of it in new + free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid anyone + to deny you these rights or to ask you to surrender the rights. These + restrictions translate to certain responsibilities for you if you + distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether gratis + or for a fee, you must give the recipients all the rights that you have. + You must make sure that they, too, receive or can get the source code. + And you must show them these terms so they know their rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, we + want its recipients to know that what they have is not the original, so + that any problems introduced by others will not reflect on the original + authors' reputations. + + Finally, any free program is threatened constantly by software patents. + We wish to avoid the danger that redistributors of a free program will + individually obtain patent licenses, in effect making the program + proprietary. To prevent this, we have made it clear that any patent must + be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and + modification follow. + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed under + the terms of this General Public License. The "Program", below, refers + to any such program or work, and a "work based on the Program" means + either the Program or any derivative work under copyright law: that is + to say, a work containing the Program or a portion of it, either + verbatim or with modifications and/or translated into another language. + (Hereinafter, translation is included without limitation in the term + "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of running + the Program is not restricted, and the output from the Program is + covered only if its contents constitute a work based on the Program + (independent of having been made by running the Program). Whether that + is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's source + code as you receive it, in any medium, provided that you conspicuously + and appropriately publish on each copy an appropriate copyright notice + and disclaimer of warranty; keep intact all the notices that refer to + this License and to the absence of any warranty; and give any other + recipients of the Program a copy of this License along with the Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion of + it, thus forming a work based on the Program, and copy and distribute + such modifications or work under the terms of Section 1 above, provided + that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any part + thereof, to be licensed as a whole at no charge to all third parties + under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this License. + (Exception: if the Program itself is interactive but does not + normally print such an announcement, your work based on the Program + is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, and + can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based on + the Program, the distribution of the whole must be on the terms of this + License, whose permissions for other licensees extend to the entire + whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of a + storage or distribution medium does not bring the other work under the + scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your cost + of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed + only for noncommercial distribution and only if you received the + program in object code or executable form with such an offer, in + accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source code + means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to control + compilation and installation of the executable. However, as a special + exception, the source code distributed need not include anything that is + normally distributed (in either source or binary form) with the major + components (compiler, kernel, and so on) of the operating system on + which the executable runs, unless that component itself accompanies the + executable. + + If distribution of executable or object code is made by offering access + to copy from a designated place, then offering equivalent access to copy + the source code from the same place counts as distribution of the source + code, even though third parties are not compelled to copy the source + along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt otherwise + to copy, modify, sublicense or distribute the Program is void, and will + automatically terminate your rights under this License. However, parties + who have received copies, or rights, from you under this License will + not have their licenses terminated so long as such parties remain in + full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and all + its terms and conditions for copying, distributing or modifying the + Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further restrictions + on the recipients' exercise of the rights granted herein. You are not + responsible for enforcing compliance by third parties to this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot distribute + so as to satisfy simultaneously your obligations under this License and + any other pertinent obligations, then as a consequence you may not + distribute the Program at all. For example, if a patent license would + not permit royalty-free redistribution of the Program by all those who + receive copies directly or indirectly through you, then the only way you + could satisfy both it and this License would be to refrain entirely from + distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is implemented + by public license practices. Many people have made generous + contributions to the wide range of software distributed through that + system in reliance on consistent application of that system; it is up to + the author/donor to decide if he or she is willing to distribute + software through any other system and a licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be + a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License may + add an explicit geographical distribution limitation excluding those + countries, so that distribution is permitted only in or among countries + not thus excluded. In such case, this License incorporates the + limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", you have the option of following the terms and + conditions either of that version or of any later version published by + the Free Software Foundation. If the Program does not specify a version + number of this License, you may choose any version ever published by the + Free Software Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted by the + Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. + EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR + OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, + EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH + YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL + NECESSARY SERVICING, REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY + AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF + THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR + OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest to + attach them to the start of each source file to most effectively convey + the exclusion of warranty; and each file should have at least the + "copyright" line and a pointer to where the full notice is found. + + One line to give the program's name and a brief idea of what it does. + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA + + Also add information on how to contact you by electronic and paper mail. + + If the program is interactive, make it output a short notice like this + when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type + `show w'. This is free software, and you are welcome to redistribute + it under certain conditions; type `show c' for details. + + The hypothetical commands `show w' and `show c' should show the + appropriate parts of the General Public License. Of course, the commands + you use may be called something other than `show w' and `show c'; they + could even be mouse-clicks or menu items--whatever suits your program. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the program, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (which makes passes at compilers) written by + James Hacker. + + signature of Ty Coon, 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your program + into proprietary programs. If your program is a subroutine library, you + may consider it more useful to permit linking proprietary applications + with the library. If this is what you want to do, use the GNU Library + General Public License instead of this License. + +--- + +## CLASSPATH EXCEPTION + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License version 2 cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from or + based on this library. If you modify this library, you may extend this + exception to your version of the library, but you are not obligated to + do so. If you do not wish to do so, delete this exception statement + from your version.
diff --git a/NOTICE.md b/NOTICE.md new file mode 100644 index 0000000..18f0422 --- /dev/null +++ b/NOTICE.md
@@ -0,0 +1,86 @@ +[//]: # " Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved. " +[//]: # " " +[//]: # " This program and the accompanying materials are made available under the " +[//]: # " terms of the Eclipse Public License v. 2.0, which is available at " +[//]: # " http://www.eclipse.org/legal/epl-2.0. " +[//]: # " " +[//]: # " This Source Code may also be made available under the following Secondary " +[//]: # " Licenses when the conditions for such availability set forth in the " +[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, " +[//]: # " version 2 with the GNU Classpath Exception, which is available at " +[//]: # " https://www.gnu.org/software/classpath/license.html. " +[//]: # " " +[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 " + +# Notices for Jakarta JSON Processing + +This content is produced and maintained by the Jakarta JSON Processing project. + +* Project home: https://projects.eclipse.org/projects/ee4j.jsonp + +## Trademarks + + Jakarta JSON Processing is a trademark of the Eclipse Foundation. + +## Copyright + +All content is the property of the respective authors or their employers. For +more information regarding authorship of content, please consult the listed +source code repository logs. + +## Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License v. 2.0 which is available at +http://www.eclipse.org/legal/epl-2.0. This Source Code may also be made +available under the following Secondary Licenses when the conditions for such +availability set forth in the Eclipse Public License v. 2.0 are satisfied: GNU +General Public License v2.0 w/Classpath exception which is available at +https://www.gnu.org/software/classpath/license.html. + +SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +## Source Code + +The project maintains the following source code repositories: + +* https://github.com/eclipse-ee4j/jsonp + +## Third-party Content + +This project leverages the following third party content. + +javax.ws.rs-api:2.0.1 (2.0.1) + +* License: (CDDL-1.1 OR GPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0) AND + Apache-2.0 +* Project: https://github.com/jax-rs/api +* Source: https://github.com/jax-rs/api + +javax.ws.rs:jsr311-api:jar:1.1.1 (1.1.1) + +* License: CDDL-1.0 AND Apache-2.0 +* Project: https://github.com/jax-rs/api +* Source: + http://search.maven.org/remotecontent?filepath=javax/ws/rs/jsr311-api/1.1.1/jsr311-api-1.1.1-sources.jar + +javax:javaee-web-api:jar:7.0 (7.0) + +* License: (CDDL-1.0 OR GPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0) AND + (EPL-1.0 OR BSD-3-Clause) AND Apache-2.0 AND LicenseRef-Public Domain +* Project: https://javaee.github.io +* Source: + http://search.maven.org/remotecontent?filepath=javax/javaee-web-api/7.0/javaee-web-api-7.0-sources.jar + +JUnit (4.12) + +* License: Eclipse Public License + +## Cryptography + +Content may contain encryption software. The country in which you are currently +may have restrictions on the import, possession, and use, and/or re-export to +another country, of encryption software. BEFORE using any encryption software, +please check the country's laws, regulations and policies concerning the import, +possession, or use, and re-export of encryption software, to see if this is +permitted. \ No newline at end of file
diff --git a/README.md b/README.md new file mode 100644 index 0000000..52567e1 --- /dev/null +++ b/README.md
@@ -0,0 +1,57 @@ +[//]: # " Copyright (c) 2018, 2021 Oracle and/or its affiliates. All rights reserved. " +[//]: # " " +[//]: # " This program and the accompanying materials are made available under the " +[//]: # " terms of the Eclipse Public License v. 2.0, which is available at " +[//]: # " http://www.eclipse.org/legal/epl-2.0. " +[//]: # " " +[//]: # " This Source Code may also be made available under the following Secondary " +[//]: # " Licenses when the conditions for such availability set forth in the " +[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, " +[//]: # " version 2 with the GNU Classpath Exception, which is available at " +[//]: # " https://www.gnu.org/software/classpath/license.html. " +[//]: # " " +[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 " + +[](https://travis-ci.org/eclipse-ee4j/jsonp) + +# Jakarta JSON Processing + +Jakarta JSON Processing provides portable APIs to parse, generate, transform, and query JSON documents. +This project contains Jakarta JSON Processing specification, API and a compatible implementation. + +## Build + +Use the following command: +```bash +mvn -U -C clean install +``` + +## License + +* Most of the Jakarta JSON Processing project source code is licensed +under the [Eclipse Public License (EPL) v2.0](https://projects.eclipse.org/license/epl-2.0) +and [GNU General Public License (GPL) v2 with Classpath Exception](https://www.gnu.org/software/classpath/license.html); +see the license information at the top of each source file. +* The source code for the demo programs is licensed +under the [Eclipse Distribution License (EDL) v1.0.](https://www.eclipse.org/org/documents/edl-v10.php). +* The binary jar files published to the Maven repository are licensed +under the same licenses as the corresponding source code; +see the file `META-INF/LICENSE.txt` in each jar file. + +You’ll find the text of the licenses in the workspace in various `LICENSE.txt` or `LICENSE.md` files. +Don’t let the presence of these license files in the workspace confuse you into thinking +that they apply to all files in the workspace. + +You should always read the license file included with every download, and read +the license text included in every source file. + +## Links + +- [Jakarta JSON Processing official web site](https://eclipse-ee4j.github.io/jsonp) +- [Jakarta JSON Processing @ Eclipse](https://projects.eclipse.org/projects/ee4j.jsonp) +- [README.txt](https://github.com/eclipse-ee4j/jsonp/blob/master/bundles/ri/src/main/resources/README.txt) + +## Contributing + +We use [contribution policy](CONTRIBUTING.md), which means we can only accept contributions under +the terms of [Eclipse Contributor Agreement](http://www.eclipse.org/legal/ECA.php).
diff --git a/api/etc/config/copyright-exclude b/api/etc/config/copyright-exclude new file mode 100644 index 0000000..e7f6f88 --- /dev/null +++ b/api/etc/config/copyright-exclude
@@ -0,0 +1,8 @@ +.json +.md +speclicense.html +MANIFEST.MF +/META-INF/services/ +/etc/config/copyright-exclude +/etc/config/copyright.txt +/bundles/ri/src/main/resources/README.txt
diff --git a/api/etc/config/copyright.txt b/api/etc/config/copyright.txt new file mode 100644 index 0000000..9c347b6 --- /dev/null +++ b/api/etc/config/copyright.txt
@@ -0,0 +1,15 @@ +/* + * Copyright (c) YYYY Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */
diff --git a/api/etc/config/exclude.xml b/api/etc/config/exclude.xml new file mode 100644 index 0000000..55ca904 --- /dev/null +++ b/api/etc/config/exclude.xml
@@ -0,0 +1,14 @@ +<!-- + + Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<FindBugsFilter> +</FindBugsFilter>
diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 0000000..e2a66bb --- /dev/null +++ b/api/pom.xml
@@ -0,0 +1,416 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.ee4j</groupId> + <artifactId>project</artifactId> + <version>1.0.6</version> + <relativePath/> + </parent> + + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + + <version>2.0.1-SNAPSHOT</version> + <name>Jakarta JSON Processing API</name> + <description>Jakarta JSON Processing defines a Java(R) based framework for parsing, generating, transforming, and querying JSON documents.</description> + <url>https://github.com/eclipse-ee4j/jsonp</url> + + <scm> + <connection>scm:git:git://github.com/eclipse-ee4j/jsonp.git</connection> + <developerConnection>scm:git:git@github.com:eclipse-ee4j/jsonp.git</developerConnection> + <url>https://github.com/eclipse-ee4j/jsonp</url> + <tag>HEAD</tag> + </scm> + + <licenses> + <license> + <name>Eclipse Public License 2.0</name> + <url>https://projects.eclipse.org/license/epl-2.0</url> + <distribution>repo</distribution> + </license> + <license> + <name>GNU General Public License, version 2 with the GNU Classpath Exception</name> + <url>https://projects.eclipse.org/license/secondary-gpl-2.0-cp</url> + <distribution>repo</distribution> + </license> + </licenses> + + <developers> + <developer> + <id>m0mus</id> + <name>Dmitry Kornilov</name> + <organization>Oracle</organization> + <roles> + <role>project lead</role> + </roles> + </developer> + <developer> + <id>lukasj</id> + <name>Lukas Jungmann</name> + <organization>Oracle</organization> + <roles> + <role>dev lead</role> + </roles> + </developer> + </developers> + + <properties> + <config.dir>${project.root.location}/etc/config</config.dir> + <copyright.exclude>${config.dir}/copyright-exclude</copyright.exclude> + <copyright.templatefile>${config.dir}/copyright.txt</copyright.templatefile> + <copyright.ignoreyear>false</copyright.ignoreyear> + <copyright.scmonly>true</copyright.scmonly> + <copyright.update>false</copyright.update> + <spotbugs.skip>false</spotbugs.skip> + <spotbugs.threshold>Low</spotbugs.threshold> + <spotbugs.version>4.2.2</spotbugs.version> + + <non.final>false</non.final> + <extension.name>jakarta.json</extension.name> + <spec.version>2.0</spec.version> + <legal.doc.source>${project.basedir}/..</legal.doc.source> + <vendor.name>Eclipse Foundation</vendor.name> + </properties> + + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.commonjava.maven.plugins</groupId> + <artifactId>directory-maven-plugin</artifactId> + <version>0.3.1</version> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>buildnumber-maven-plugin</artifactId> + <version>1.4</version> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>3.2.0</version> + </plugin> + <plugin> + <groupId>org.glassfish.copyright</groupId> + <artifactId>glassfish-copyright-maven-plugin</artifactId> + <version>2.4</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + </plugin> + <plugin> + <groupId>org.glassfish.build</groupId> + <artifactId>spec-version-maven-plugin</artifactId> + <version>2.1</version> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>5.1.1</version> + <configuration> + <instructions> + <_noextraheaders>true</_noextraheaders> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.2.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.2.1</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>3.2.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <version>3.0.0-M3</version> + </plugin> + <plugin> + <groupId>com.github.spotbugs</groupId> + <artifactId>spotbugs-maven-plugin</artifactId> + <version>${spotbugs.version}</version> + </plugin> + </plugins> + </pluginManagement> + + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <executions> + <execution> + <id>enforce-maven</id> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireJavaVersion> + <version>[11,)</version> + </requireJavaVersion> + <requireMavenVersion> + <version>[3.6.0,)</version> + </requireMavenVersion> + </rules> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.commonjava.maven.plugins</groupId> + <artifactId>directory-maven-plugin</artifactId> + <executions> + <execution> + <id>find-project-root</id> + <phase>validate</phase> + <goals> + <goal>highest-basedir</goal> + </goals> + <configuration> + <property>project.root.location</property> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <!-- Requires validate target to initialize copyright.config.dir properly --> + <!-- e.g. mvn validate glassfish-copyright:repair --> + <groupId>org.glassfish.copyright</groupId> + <artifactId>glassfish-copyright-maven-plugin</artifactId> + <configuration> + <excludeFile>${copyright.exclude}</excludeFile> + <scmOnly>${copyright.scmonly}</scmOnly> + <update>${copyright.update}</update> + <ignoreYear>${copyright.ignoreyear}</ignoreYear> + <quiet>false</quiet> + </configuration> + <executions> + <execution> + <phase>verify</phase> + <goals> + <goal>check</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>buildnumber-maven-plugin</artifactId> + <executions> + <execution> + <id>validate</id> + <phase>validate</phase> + <goals> + <goal>create</goal> + </goals> + <configuration> + <getRevisionOnlyOnce>true</getRevisionOnlyOnce> + <shortRevisionLength>7</shortRevisionLength> + <revisionOnScmFailure>false</revisionOnScmFailure> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>add-legal-resource</id> + <phase>generate-resources</phase> + <goals> + <goal>add-resource</goal> + </goals> + <configuration> + <resources> + <resource> + <directory>${legal.doc.source}</directory> + <includes> + <include>NOTICE.md</include> + <include>LICENSE.md</include> + </includes> + <targetPath>META-INF</targetPath> + </resource> + </resources> + </configuration> + </execution> + <execution> + <id>currentyear-property</id> + <goals> + <goal>timestamp-property</goal> + </goals> + <phase>validate</phase> + <configuration> + <name>current.year</name> + <locale>en,US</locale> + <pattern>yyyy</pattern> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <release>9</release> + <compilerArgs> + <arg>-Xlint:all</arg> + </compilerArgs> + </configuration> + <executions> + <execution> + <id>base-compile</id> + <goals> + <goal>compile</goal> + </goals> + <configuration> + <release>8</release> + <excludes> + <exclude>module-info.java</exclude> + </excludes> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.glassfish.build</groupId> + <artifactId>spec-version-maven-plugin</artifactId> + <configuration> + <spec> + <nonFinal>${non.final}</nonFinal> + <jarType>api</jarType> + <specVersion>${spec.version}</specVersion> + <specImplVersion>${project.version}</specImplVersion> + <apiPackage>${extension.name}</apiPackage> + </spec> + </configuration> + <executions> + <execution> + <goals> + <goal>set-spec-properties</goal> + <!-- TODO: + glassfish-spec-version-maven-plugin needs to be updated + in order to check 'jakarta.' prefixed values in manifest entries + --> + <!--<goal>check-module</goal>--> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Bundle-Version>${spec.bundle.version}</Bundle-Version> + <Bundle-SymbolicName>${spec.bundle.symbolic-name}</Bundle-SymbolicName> + <Extension-Name>${spec.extension.name}</Extension-Name> + <Implementation-Version>${spec.implementation.version}</Implementation-Version> + <Specification-Version>${spec.specification.version}</Specification-Version> + <Bundle-Description>Jakarta JSON Processing API ${spec.version}</Bundle-Description> + <Specification-Vendor>${vendor.name}</Specification-Vendor> + <Implementation-Build-Id>${buildNumber}</Implementation-Build-Id> + </instructions> + </configuration> + <executions> + <execution> + <id>bundle-manifest</id> + <phase>process-classes</phase> + <goals> + <goal>manifest</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addDefaultEntries>false</addDefaultEntries> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + </manifest> + <manifestEntries> + <Implementation-Build-Id>${buildNumber}</Implementation-Build-Id> + </manifestEntries> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addDefaultEntries>false</addDefaultEntries> + </manifest> + </archive> + <release>11</release> + <notimestamp>true</notimestamp> + <docfilessubdirs>true</docfilessubdirs> + <description>JSON Processing API documentation</description> + <doctitle>JSON Processing API documentation</doctitle> + <windowtitle>JSON Processing API documentation</windowtitle> + <header><![CDATA[<br>JSON Processing API v${project.version}]]></header> + <bottom><![CDATA[ +Comments to: <a href="mailto:jsonp-dev@eclipse.org">jsonp-dev@eclipse.org</a>.<br> +Copyright © 2019, ${current.year} Eclipse Foundation. All rights reserved.<br> +Use is subject to <a href="{@docRoot}/doc-files/speclicense.html" target="_top">license terms</a>.]]> + </bottom> + </configuration> + </plugin> + <plugin> + <groupId>com.github.spotbugs</groupId> + <artifactId>spotbugs-maven-plugin</artifactId> + <configuration> + <skip>${spotbugs.skip}</skip> + <threshold>${spotbugs.threshold}</threshold> + <findbugsXmlWithMessages>true</findbugsXmlWithMessages> + <fork>true</fork> + </configuration> + </plugin> + </plugins> + </build> + +</project>
diff --git a/api/src/main/java/jakarta/json/EmptyArray.java b/api/src/main/java/jakarta/json/EmptyArray.java new file mode 100644 index 0000000..9d48dc2 --- /dev/null +++ b/api/src/main/java/jakarta/json/EmptyArray.java
@@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collections; +import java.util.List; +import java.util.RandomAccess; + +/** + * Private implementation of immutable {@link JsonArray}. + * + * @author Lukas Jungmann + */ +final class EmptyArray extends AbstractList<JsonValue> implements JsonArray, Serializable, RandomAccess { + + private static final long serialVersionUID = 7295439472061642859L; + + @Override + public JsonValue get(int index) { + throw new IndexOutOfBoundsException("Index: " + index); + } + + @Override + public int size() { + return 0; + } + + @Override + public JsonObject getJsonObject(int index) { + return (JsonObject) get(index); + } + + @Override + public JsonArray getJsonArray(int index) { + return (JsonArray) get(index); + } + + @Override + public JsonNumber getJsonNumber(int index) { + return (JsonNumber) get(index); + } + + @Override + public JsonString getJsonString(int index) { + return (JsonString) get(index); + } + + @Override + public <T extends JsonValue> List<T> getValuesAs(Class<T> clazz) { + return Collections.emptyList(); + } + + @Override + public String getString(int index) { + return getJsonString(index).getString(); + } + + @Override + public String getString(int index, String defaultValue) { + return defaultValue; + } + + @Override + public int getInt(int index) { + return getJsonNumber(index).intValue(); + } + + @Override + public int getInt(int index, int defaultValue) { + return defaultValue; + } + + @Override + public boolean getBoolean(int index) { + return get(index) == JsonValue.TRUE; + } + + @Override + public boolean getBoolean(int index, boolean defaultValue) { + return defaultValue; + } + + @Override + public boolean isNull(int index) { + return get(index) == JsonValue.NULL; + } + + @Override + public ValueType getValueType() { + return ValueType.ARRAY; + } + + // Preserves singleton property + private Object readResolve() { + return JsonValue.EMPTY_JSON_ARRAY; + } +}
diff --git a/api/src/main/java/jakarta/json/EmptyObject.java b/api/src/main/java/jakarta/json/EmptyObject.java new file mode 100644 index 0000000..fa3254d --- /dev/null +++ b/api/src/main/java/jakarta/json/EmptyObject.java
@@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.io.Serializable; +import java.util.AbstractMap; +import java.util.Collections; +import java.util.Set; + +/** + * Private implementation of immutable {@link JsonObject}. + * + * @author Lukas Jungmann + */ +final class EmptyObject extends AbstractMap<String, JsonValue> implements JsonObject, Serializable { + + private static final long serialVersionUID = -1461653546889072583L; + + @Override + public Set<Entry<String, JsonValue>> entrySet() { + return Collections.<Entry<String, JsonValue>>emptySet(); + } + + @Override + public JsonArray getJsonArray(String name) { + return (JsonArray) get(name); + } + + @Override + public JsonObject getJsonObject(String name) { + return (JsonObject) get(name); + } + + @Override + public JsonNumber getJsonNumber(String name) { + return (JsonNumber) get(name); + } + + @Override + public JsonString getJsonString(String name) { + return (JsonString) get(name); + } + + @Override + public String getString(String name) { + return getJsonString(name).getString(); + } + + @Override + public String getString(String name, String defaultValue) { + return defaultValue; + } + + @Override + public int getInt(String name) { + return getJsonNumber(name).intValue(); + } + + @Override + public int getInt(String name, int defaultValue) { + return defaultValue; + } + + @Override + public boolean getBoolean(String name) { + throw new NullPointerException(); + } + + @Override + public boolean getBoolean(String name, boolean defaultValue) { + return defaultValue; + } + + @Override + public boolean isNull(String name) { + throw new NullPointerException(); + } + + @Override + public ValueType getValueType() { + return ValueType.OBJECT; + } + + // Preserves singleton property + private Object readResolve() { + return JsonValue.EMPTY_JSON_OBJECT; + } +}
diff --git a/api/src/main/java/jakarta/json/Json.java b/api/src/main/java/jakarta/json/Json.java new file mode 100644 index 0000000..cdbc7ee --- /dev/null +++ b/api/src/main/java/jakarta/json/Json.java
@@ -0,0 +1,520 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonGeneratorFactory; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParserFactory; + +/** + * Factory class for creating JSON processing objects. + * This class provides the most commonly used methods for creating these + * objects and their corresponding factories. The factory classes provide + * all the various ways to create these objects. + * + * <p> + * The methods in this class locate a provider instance using the method + * {@link JsonProvider#provider()}. This class uses the provider instance + * to create JSON processing objects. + * + * <p> + * The following example shows how to create a JSON parser to parse + * an empty array: + * <pre> + * <code> + * StringReader reader = new StringReader("[]"); + * JsonParser parser = Json.createParser(reader); + * </code> + * </pre> + * + * <p> + * All the methods in this class are safe for use by multiple concurrent + * threads. + */ +public final class Json { + + private Json() { + } + + /** + * Creates a JSON parser from a character stream. + * + * @param reader i/o reader from which JSON is to be read + * @return a JSON parser + */ + public static JsonParser createParser(Reader reader) { + return JsonProvider.provider().createParser(reader); + } + + /** + * Creates a JSON parser from a byte stream. + * The character encoding of the stream is determined as specified in + * <a href="http://tools.ietf.org/rfc/rfc7159.txt">RFC 7159</a>. + * + * @param in i/o stream from which JSON is to be read + * @throws JsonException if encoding cannot be determined + * or i/o error (IOException would be cause of JsonException) + * @return a JSON parser + */ + public static JsonParser createParser(InputStream in) { + return JsonProvider.provider().createParser(in); + } + + /** + * Creates a JSON generator for writing JSON to a character stream. + * + * @param writer a i/o writer to which JSON is written + * @return a JSON generator + */ + public static JsonGenerator createGenerator(Writer writer) { + return JsonProvider.provider().createGenerator(writer); + } + + /** + * Creates a JSON generator for writing JSON to a byte stream. + * + * @param out i/o stream to which JSON is written + * @return a JSON generator + */ + public static JsonGenerator createGenerator(OutputStream out) { + return JsonProvider.provider().createGenerator(out); + } + + /** + * Creates a parser factory for creating {@link JsonParser} objects. + * + * @return JSON parser factory. + * + public static JsonParserFactory createParserFactory() { + return JsonProvider.provider().createParserFactory(); + } + */ + + /** + * Creates a parser factory for creating {@link JsonParser} objects. + * The factory is configured with the specified map of provider specific + * configuration properties. Provider implementations should ignore any + * unsupported configuration properties specified in the map. + * + * @param config a map of provider specific properties to configure the + * JSON parsers. The map may be empty or null + * @return JSON parser factory + */ + public static JsonParserFactory createParserFactory(Map<String, ?> config) { + return JsonProvider.provider().createParserFactory(config); + } + + /** + * Creates a generator factory for creating {@link JsonGenerator} objects. + * + * @return JSON generator factory + * + public static JsonGeneratorFactory createGeneratorFactory() { + return JsonProvider.provider().createGeneratorFactory(); + } + */ + + /** + * Creates a generator factory for creating {@link JsonGenerator} objects. + * The factory is configured with the specified map of provider specific + * configuration properties. Provider implementations should ignore any + * unsupported configuration properties specified in the map. + * + * @param config a map of provider specific properties to configure the + * JSON generators. The map may be empty or null + * @return JSON generator factory + */ + public static JsonGeneratorFactory createGeneratorFactory( + Map<String, ?> config) { + return JsonProvider.provider().createGeneratorFactory(config); + } + + /** + * Creates a JSON writer to write a + * JSON {@link JsonObject object} or {@link JsonArray array} + * structure to the specified character stream. + * + * @param writer to which JSON object or array is written + * @return a JSON writer + */ + public static JsonWriter createWriter(Writer writer) { + return JsonProvider.provider().createWriter(writer); + } + + /** + * Creates a JSON writer to write a + * JSON {@link JsonObject object} or {@link JsonArray array} + * structure to the specified byte stream. Characters written to + * the stream are encoded into bytes using UTF-8 encoding. + * + * @param out to which JSON object or array is written + * @return a JSON writer + */ + public static JsonWriter createWriter(OutputStream out) { + return JsonProvider.provider().createWriter(out); + } + + /** + * Creates a JSON reader from a character stream. + * + * @param reader a reader from which JSON is to be read + * @return a JSON reader + */ + public static JsonReader createReader(Reader reader) { + return JsonProvider.provider().createReader(reader); + } + + /** + * Creates a JSON reader from a byte stream. The character encoding of + * the stream is determined as described in + * <a href="http://tools.ietf.org/rfc/rfc7159.txt">RFC 7159</a>. + * + * @param in a byte stream from which JSON is to be read + * @return a JSON reader + */ + public static JsonReader createReader(InputStream in) { + return JsonProvider.provider().createReader(in); + } + + /** + * Creates a reader factory for creating {@link JsonReader} objects. + * The factory is configured with the specified map of provider specific + * configuration properties. Provider implementations should ignore any + * unsupported configuration properties specified in the map. + * + * @param config a map of provider specific properties to configure the + * JSON readers. The map may be empty or null + * @return a JSON reader factory + */ + public static JsonReaderFactory createReaderFactory(Map<String, ?> config) { + return JsonProvider.provider().createReaderFactory(config); + } + + /** + * Creates a writer factory for creating {@link JsonWriter} objects. + * The factory is configured with the specified map of provider specific + * configuration properties. Provider implementations should ignore any + * unsupported configuration properties specified in the map. + * + * @param config a map of provider specific properties to configure the + * JSON writers. The map may be empty or null + * @return a JSON writer factory + */ + public static JsonWriterFactory createWriterFactory(Map<String, ?> config) { + return JsonProvider.provider().createWriterFactory(config); + } + + /** + * Creates a JSON array builder + * + * @return a JSON array builder + */ + public static JsonArrayBuilder createArrayBuilder() { + return JsonProvider.provider().createArrayBuilder(); + } + + /** + * Creates a JSON array builder, initialized with the specified array + * + * @param array the initial array in the builder + * @return a JSON array builder + * + * @since 1.1 + */ + public static JsonArrayBuilder createArrayBuilder(JsonArray array) { + return JsonProvider.provider().createArrayBuilder(array); + } + + /** + * Creates a JSON array builder, initialized with the content of specified {@code collection}. + * If the @{code collection} contains {@link Optional}s then resulting JSON array builder + * contains the value from the {@code collection} only if the {@link Optional} is not empty. + * + * @param collection the initial data for the builder + * @return a JSON array builder + * @exception IllegalArgumentException if the value from the {@code collection} cannot be converted + * to the corresponding {@link JsonValue} + * + * @since 1.1 + */ + public static JsonArrayBuilder createArrayBuilder(Collection<?> collection) { + return JsonProvider.provider().createArrayBuilder(collection); + } + + /** + * Creates a JSON object builder + * + * @return a JSON object builder + */ + public static JsonObjectBuilder createObjectBuilder() { + return JsonProvider.provider().createObjectBuilder(); + } + + /** + * Creates a JSON object builder, initialized with the specified object. + * + * @param object the initial object in the builder + * @return a JSON object builder + * + * @since 1.1 + */ + public static JsonObjectBuilder createObjectBuilder(JsonObject object) { + return JsonProvider.provider().createObjectBuilder(object); + } + + /** + * Creates a JSON object builder, initialized with the data from specified {@code map}. + * If the @{code map} contains {@link Optional}s then resulting JSON object builder + * contains the key from the {@code map} only if the {@link Optional} is not empty. + * + * @param map the initial object in the builder + * @return a JSON object builder + * @exception IllegalArgumentException if the value from the {@code map} cannot be converted + * to the corresponding {@link JsonValue} + * + * @since 1.1 + */ + public static JsonObjectBuilder createObjectBuilder(Map<String, Object> map) { + return JsonProvider.provider().createObjectBuilder(map); + } + + /** + * Creates JSON Pointer (<a href="http://tools.ietf.org/html/rfc6901">RFC 6901</a>) + * from given {@code jsonPointer} string. + * <ul> + * <li>An empty {@code jsonPointer} string defines a reference to the target itself.</li> + * <li>If the {@code jsonPointer} string is non-empty, it must be a sequence of '{@code /}' prefixed tokens.</li> + * </ul> + * + * @param jsonPointer the valid escaped JSON Pointer string + * @throws NullPointerException if {@code jsonPointer} is {@code null} + * @throws JsonException if {@code jsonPointer} is not a valid JSON Pointer + * @return a JSON Pointer + * + * @since 1.1 + */ + public static JsonPointer createPointer(String jsonPointer) { + return JsonProvider.provider().createPointer(jsonPointer); + } + + /** + * Creates a JSON Patch builder (<a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>). + * + * @return a JSON Patch builder + * + * @since 1.1 + */ + public static JsonPatchBuilder createPatchBuilder() { + return JsonProvider.provider().createPatchBuilder(); + } + + /** + * Creates a JSON Patch builder + * (<a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>), + * initialized with the specified operations. + * + * @param array the initial patch operations + * @return a JSON Patch builder + * + * @since 1.1 + */ + public static JsonPatchBuilder createPatchBuilder(JsonArray array) { + return JsonProvider.provider().createPatchBuilder(array); + } + + /** + * Creates a JSON Patch (<a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>) + * from the specified operations. + * + * @param array patch operations + * @return a JSON Patch + * + * @since 1.1 + */ + public static JsonPatch createPatch(JsonArray array) { + return JsonProvider.provider().createPatch(array); + } + + /** + * Generates a JSON Patch (<a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>) + * from the source and target {@code JsonStructure}. + * The generated JSON Patch need not be unique. + * + * @param source the source + * @param target the target, must be the same type as the source + * @return a JSON Patch which when applied to the source, yields the target + * + * @since 1.1 + */ + public static JsonPatch createDiff(JsonStructure source, JsonStructure target) { + return JsonProvider.provider().createDiff(source, target); + } + + /** + * Creates JSON Merge Patch (<a href="http://tools.ietf.org/html/rfc7396">RFC 7396</a>) + * from specified {@code JsonValue}. + * + * @param patch the patch + * @return a JSON Merge Patch + * + * @since 1.1 + */ + public static JsonMergePatch createMergePatch(JsonValue patch) { + return JsonProvider.provider().createMergePatch(patch); + } + + /** + * Generates a JSON Merge Patch (<a href="http://tools.ietf.org/html/rfc7396">RFC 7396</a>) + * from the source and target {@code JsonValue}s + * which when applied to the {@code source}, yields the {@code target}. + * + * @param source the source + * @param target the target + * @return a JSON Merge Patch + * + * @since 1.1 + */ + public static JsonMergePatch createMergeDiff(JsonValue source, JsonValue target) { + return JsonProvider.provider().createMergeDiff(source, target); + } + + /** + * Creates a builder factory for creating {@link JsonArrayBuilder} + * and {@link JsonObjectBuilder} objects. + * The factory is configured with the specified map of provider specific + * configuration properties. Provider implementations should ignore any + * unsupported configuration properties specified in the map. + * + * @param config a map of provider specific properties to configure the + * JSON builders. The map may be empty or null + * @return a JSON builder factory + */ + public static JsonBuilderFactory createBuilderFactory( + Map<String, ?> config) { + return JsonProvider.provider().createBuilderFactory(config); + } + + /** + * Creates a JsonString. + * + * @param value a JSON string + * @return the JsonString for the string + * + * @since 1.1 + */ + public static JsonString createValue(String value) { + return JsonProvider.provider().createValue(value); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public static JsonNumber createValue(int value) { + return JsonProvider.provider().createValue(value); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public static JsonNumber createValue(long value) { + return JsonProvider.provider().createValue(value); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public static JsonNumber createValue(double value) { + return JsonProvider.provider().createValue(value); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public static JsonNumber createValue(BigDecimal value) { + return JsonProvider.provider().createValue(value); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public static JsonNumber createValue(BigInteger value) { + return JsonProvider.provider().createValue(value); + } + + /** + * Encodes (escapes) a passed string as defined by <a href="http://tools.ietf.org/html/rfc6901">RFC 6901</a>. + * This method doesn't validate the passed JSON-pointer string. + * + * @param pointer the JSON-pointer string to encode + * @return encoded JSON-pointer string + * + * @since 1.1 + */ + public static String encodePointer(String pointer) { + return pointer.replace("~", "~0").replace("/", "~1"); + } + + /** + * Decodes a passed JSON-pointer string as defined by <a href="http://tools.ietf.org/html/rfc6901">RFC 6901</a>. + * This method doesn't validate the passed JSON-pointer string. + * + * @param escaped the JSON-pointer string to decode + * @return decoded JSON-pointer string + * + * @since 1.1 + */ + public static String decodePointer(String escaped) { + return escaped.replace("~1", "/").replace("~0", "~"); + } + +}
diff --git a/api/src/main/java/jakarta/json/JsonArray.java b/api/src/main/java/jakarta/json/JsonArray.java new file mode 100644 index 0000000..7c39674 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonArray.java
@@ -0,0 +1,274 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * {@code JsonArray} represents an immutable JSON array + * (an ordered sequence of zero or more values). + * It also provides an unmodifiable list view of the values in the array. + * + * <p>A {@code JsonArray} object can be created by reading JSON data from + * an input source or it can be built from scratch using an array builder + * object. + * + * <p>The following example demonstrates how to create a {@code JsonArray} + * object from an input source using the method {@link JsonReader#readArray()}: + * <pre><code> + * JsonReader jsonReader = Json.createReader(...); + * JsonArray array = jsonReader.readArray(); + * jsonReader.close(); + * </code></pre> + * + * <p>The following example demonstrates how to build an empty JSON array + * using the class {@link JsonArrayBuilder}: + * <pre><code> + * JsonArray array = Json.createArrayBuilder().build(); + * </code></pre> + * + * <p>The example code below demonstrates how to create the following JSON array: + * <pre><code> + * [ + * { "type": "home", "number": "212 555-1234" }, + * { "type": "fax", "number": "646 555-4567" } + * ] + * </code></pre> + * <pre><code> + * JsonArray value = Json.createArrayBuilder() + * .add(Json.createObjectBuilder() + * .add("type", "home") + * .add("number", "212 555-1234")) + * .add(Json.createObjectBuilder() + * .add("type", "fax") + * .add("number", "646 555-4567")) + * .build(); + * </code></pre> + * + * <p>The following example demonstrates how to write a {@code JsonArray} object + * as JSON data: + * <pre><code> + * JsonArray arr = ...; + * JsonWriter writer = Json.createWriter(...) + * writer.writeArray(arr); + * writer.close(); + * </code></pre> + * + * <p>The values in a {@code JsonArray} can be of the following types: + * {@link JsonObject}, {@link JsonArray}, + * {@link JsonString}, {@link JsonNumber}, {@link JsonValue#TRUE}, + * {@link JsonValue#FALSE}, and {@link JsonValue#NULL}. + * {@code JsonArray} provides various accessor methods to access the values + * in an array. + * + * <p>The following example shows how to obtain the home phone number + * "212 555-1234" from the array built in the previous example: + * <pre><code> + * JsonObject home = array.getJsonObject(0); + * String number = home.getString("number"); + * </code></pre> + * + * <p>{@code JsonArray} instances are list objects that provide read-only + * access to the values in the JSON array. Any attempt to modify the list, + * whether directly or using its collection views, results in an + * {@code UnsupportedOperationException}. + */ +public interface JsonArray extends JsonStructure, List<JsonValue> { + + /** + * Returns the object value at the specified position in this array. + * This is a convenience method for {@code (JsonObject)get(index)}. + * + * @param index index of the value to be returned + * @return the value at the specified position in this array + * @throws IndexOutOfBoundsException if the index is out of range + * @throws ClassCastException if the value at the specified position is not + * assignable to the JsonObject type + */ + JsonObject getJsonObject(int index); + + /** + * Returns the array value at the specified position in this array. + * This is a convenience method for {@code (JsonArray)get(index)}. + * + * @param index index of the value to be returned + * @return the value at the specified position in this array + * @throws IndexOutOfBoundsException if the index is out of range + * @throws ClassCastException if the value at the specified position is not + * assignable to the JsonArray type + */ + JsonArray getJsonArray(int index); + + /** + * Returns the number value at the specified position in this array. + * This is a convenience method for {@code (JsonNumber)get(index)}. + * + * @param index index of the value to be returned + * @return the value at the specified position in this array + * @throws IndexOutOfBoundsException if the index is out of range + * @throws ClassCastException if the value at the specified position is not + * assignable to the JsonNumber type + */ + JsonNumber getJsonNumber(int index); + + /** + * Returns the string value at ths specified position in this array. + * This is a convenience method for {@code (JsonString)get(index)}. + * + * @param index index of the value to be returned + * @return the value at the specified position in this array + * @throws IndexOutOfBoundsException if the index is out of range + * @throws ClassCastException if the value at the specified position is not + * assignable to the JsonString type + */ + JsonString getJsonString(int index); + + /** + * Returns a list view of the specified type for the array. This method + * does not verify if there is a value of wrong type in the array. Providing + * this typesafe view dynamically may cause a program fail with a + * {@code ClassCastException}, if there is a value of wrong type in this + * array. Unfortunately, the exception can occur at any time after this + * method returns. + * + * @param <T> The type of the List for the array + * @param clazz a JsonValue type + * @return a list view of the specified type + */ + <T extends JsonValue> List<T> getValuesAs(Class<T> clazz); + + /** + * Returns a list view for the array. The value and the type of the elements + * in the list is specified by the {@code func} argument. + * <p>This method can be used to obtain a list of the unwrapped types, such as + * <pre>{@code + * List<String> strings = ary1.getValuesAs(JsonString::getString); + * List<Integer> ints = ary2.getValuesAs(JsonNumber::intValue); + * } </pre> + * or a list of simple projections, such as + * <pre> {@code + * List<Integer> stringsizes = ary1.getValueAs((JsonString v)->v.getString().length(); + * } </pre> + * @param <K> The element type (must be a subtype of JsonValue) of this JsonArray. + * @param <T> The element type of the returned List + * @param func The function that maps the elements of this JsonArray to the target elements. + * @return A List of the specified values and type. + * @throws ClassCastException if the {@code JsonArray} contains a value of wrong type + * + * @since 1.1 + */ + default <T, K extends JsonValue> List<T> getValuesAs(Function<K, T> func) { + @SuppressWarnings("unchecked") + Stream<K> stream = (Stream<K>) stream(); + return stream.map(func).collect(Collectors.toList()); + } + + /** + * A convenience method for + * {@code getJsonString(index).getString()}. + * + * @param index index of the {@code JsonString} value + * @return the String value at the specified position + * @throws IndexOutOfBoundsException if the index is out of range + * @throws ClassCastException if the value at the specified position is not + * assignable to {@code JsonString} + */ + String getString(int index); + + /** + * Returns the {@code String} value of {@code JsonString} at the specified + * position in this JSON array values. If {@code JsonString} is found, + * its {@link jakarta.json.JsonString#getString()} is returned. Otherwise, + * the specified default value is returned. + * + * @param index index of the {@code JsonString} value + * @param defaultValue the String to return if the {@code JsonValue} at the + * specified position is not a {@code JsonString} + * @return the String value at the specified position in this array, + * or the specified default value + */ + String getString(int index, String defaultValue); + + /** + * A convenience method for + * {@code getJsonNumber(index).intValue()}. + * + * @param index index of the {@code JsonNumber} value + * @return the int value at the specified position + * @throws IndexOutOfBoundsException if the index is out of range + * @throws ClassCastException if the value at the specified position is not + * assignable to {@code JsonNumber} + */ + int getInt(int index); + + /** + * Returns the int value of the {@code JsonNumber} at the specified position. + * If the value at that position is a {@code JsonNumber}, + * this method returns {@link jakarta.json.JsonNumber#intValue()}. Otherwise + * this method returns the specified default value. + * + * @param index index of the {@code JsonNumber} value + * @param defaultValue the int value to return if the {@code JsonValue} at + * the specified position is not a {@code JsonNumber} + * @return the int value at the specified position in this array, + * or the specified default value + */ + int getInt(int index, int defaultValue); + + /** + * Returns the boolean value at the specified position. + * If the value at the specified position is {@code JsonValue.TRUE} + * this method returns {@code true}. If the value at the specified position + * is {@code JsonValue.FALSE} this method returns {@code false}. + * + * @param index index of the JSON boolean value + * @return the boolean value at the specified position + * @throws IndexOutOfBoundsException if the index is out of range + * @throws ClassCastException if the value at the specified position is not + * assignable to {@code JsonValue.TRUE} or {@code JsonValue.FALSE} + */ + boolean getBoolean(int index); + + /** + * Returns the boolean value at the specified position. + * If the value at the specified position is {@code JsonValue.TRUE} + * this method returns {@code true}. If the value at the specified position + * is {@code JsonValue.FALSE} this method returns {@code false}. + * Otherwise this method returns the specified default value. + * + * @param index index of the JSON boolean value + * @param defaultValue the boolean value to return if the {@code JsonValue} + * at the specified position is neither TRUE nor FALSE + * @return the boolean value at the specified position, + * or the specified default value + */ + boolean getBoolean(int index, boolean defaultValue); + + /** + * Returns {@code true} if the value at the specified location in this + * array is {@code JsonValue.NULL}. + * + * @param index index of the JSON null value + * @return return true if the value at the specified location is + * {@code JsonValue.NULL}, otherwise false + * @throws IndexOutOfBoundsException if the index is out of range + */ + boolean isNull(int index); +}
diff --git a/api/src/main/java/jakarta/json/JsonArrayBuilder.java b/api/src/main/java/jakarta/json/JsonArrayBuilder.java new file mode 100644 index 0000000..db0c935 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonArrayBuilder.java
@@ -0,0 +1,622 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * A builder for creating {@link JsonArray} models from scratch, and for + * modifying a existing {@code JsonArray}. + * <p>A {@code JsonArrayBuilder} can start with an empty or a non-empty + * JSON array model. This interface provides methods to add, insert, remove + * and replace values in the JSON array model.</p> + * <p>Methods in this class can be chained to perform multiple values to + * the array.</p> + * + * <p>The class {@link jakarta.json.Json} contains methods to create the builder + * object. The example code below shows how to build an empty {@code JsonArray} + * instance. + * <pre> + * <code> + * JsonArray array = Json.createArrayBuilder().build(); + * </code> + * </pre> + * + * <p>The class {@link JsonBuilderFactory} also contains methods to create + * {@code JsonArrayBuilder} instances. A factory instance can be used to create + * multiple builder instances with the same configuration. This the preferred + * way to create multiple instances. + * + * The example code below shows how to build a {@code JsonArray} object + * that represents the following JSON array: + * + * <pre> + * <code> + * [ + * { "type": "home", "number": "212 555-1234" }, + * { "type": "fax", "number": "646 555-4567" } + * ] + * </code> + * </pre> + * + * <p>The following code creates the JSON array above: + * + * <pre> + * <code> + * JsonBuilderFactory factory = Json.createBuilderFactory(config); + * JsonArray value = factory.createArrayBuilder() + * .add(factory.createObjectBuilder() + * .add("type", "home") + * .add("number", "212 555-1234")) + * .add(factory.createObjectBuilder() + * .add("type", "fax") + * .add("number", "646 555-4567")) + * .build(); + * </code> + * </pre> + * + * <p>This class does <em>not</em> allow <code>null</code> to be used as a + * value while building the JSON array + * + * @see JsonObjectBuilder + */ +public interface JsonArrayBuilder { + + /** + * Adds a value to the array. + * + * @param value the JSON value + * @return this array builder + * @throws NullPointerException if the specified value is null + */ + JsonArrayBuilder add(JsonValue value); + + /** + * Adds a value to the array as a {@link JsonString}. + * + * @param value the string value + * @return this array builder + * @throws NullPointerException if the specified value is null + */ + JsonArrayBuilder add(String value); + + /** + * Adds a value to the array as a {@link JsonNumber}. + * + * @param value the number value + * @return this array builder + * @throws NullPointerException if the specified value is null + * + * @see JsonNumber + */ + JsonArrayBuilder add(BigDecimal value); + + /** + * Adds a value to the array as a {@link JsonNumber}. + * + * @param value the number value + * @return this array builder + * @throws NullPointerException if the specified value is null + * + * @see JsonNumber + */ + JsonArrayBuilder add(BigInteger value); + + /** + * Adds a value to the array as a {@link JsonNumber}. + * + * @param value the number value + * @return this array builder + * + * @see JsonNumber + */ + JsonArrayBuilder add(int value); + + /** + * Adds a value to the array as a {@link JsonNumber}. + * + * @param value the number value + * @return this array builder + * + * @see JsonNumber + */ + JsonArrayBuilder add(long value); + + /** + * Adds a value to the array as a {@link JsonNumber}. + * + * @param value the number value + * @return this array builder + * @throws NumberFormatException if the value is Not-a-Number (NaN) or + * infinity + * + * @see JsonNumber + */ + JsonArrayBuilder add(double value); + + /** + * Adds a {@link JsonValue#TRUE} or {@link JsonValue#FALSE} value to the + * array. + * + * @param value the boolean value + * @return this array builder + */ + JsonArrayBuilder add(boolean value); + + /** + * Adds a {@link JsonValue#NULL} value to the array. + * + * @return this array builder + */ + JsonArrayBuilder addNull(); + + /** + * Adds a {@link JsonObject} from an object builder to the array. + * + * @param builder the object builder + * @return this array builder + * @throws NullPointerException if the specified builder is null + */ + JsonArrayBuilder add(JsonObjectBuilder builder); + + /** + * Adds a {@link JsonArray} from an array builder to the array. + * + * @param builder the array builder + * @return this array builder + * @throws NullPointerException if the specified builder is null + */ + JsonArrayBuilder add(JsonArrayBuilder builder); + + /** + * Adds all elements of the array in the specified array builder to the array. + * + * @param builder the array builder + * @return this array builder + * @throws NullPointerException if the specified builder is null + * + @since 1.1 + */ + default JsonArrayBuilder addAll(JsonArrayBuilder builder) { + throw new UnsupportedOperationException(); + } + + /** + * Inserts a value to the array at the specified position. Shifts the value + * currently at that position (if any) and any subsequent values to the right + * (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param value the JSON value + * @return this array builder + * @throws NullPointerException if the specified value is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, JsonValue value) { + throw new UnsupportedOperationException(); + } + + /** + * Adds a value to the array as a {@link JsonString} at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param value the string value + * @return this array builder + * @throws NullPointerException if the specified value is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, String value) { + throw new UnsupportedOperationException(); + } + + /** + * Adds a value to the array as a {@link JsonNumber} at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws NullPointerException if the specified value is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, BigDecimal value) { + throw new UnsupportedOperationException(); + } + + /** + * Adds a value to the array as a {@link JsonNumber} at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws NullPointerException if the specified value is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, BigInteger value) { + throw new UnsupportedOperationException(); + } + + /** + * Adds a value to the array as a {@link JsonNumber} at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, int value) { + throw new UnsupportedOperationException(); + } + + /** + * Adds a value to the array as a {@link JsonNumber} at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, long value) { + throw new UnsupportedOperationException(); + } + + /** + * Adds a value to the array as a {@link JsonNumber} at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws NumberFormatException if the value is Not-a-Number (NaN) or + * infinity + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, double value) { + throw new UnsupportedOperationException(); + } + + /** + * Adds a {@link JsonValue#TRUE} or {@link JsonValue#FALSE} value to the + * array at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param value the boolean value + * @return this array builder + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, boolean value) { + throw new UnsupportedOperationException(); + } + + /** + * Adds a {@link JsonValue#NULL} value to the array at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @return this array builder + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder addNull(int index) { + return add(index, JsonValue.NULL); + } + + /** + * Adds a {@link JsonObject} from an object builder to the array at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param builder the object builder + * @return this array builder + * @throws NullPointerException if the specified builder is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, JsonObjectBuilder builder) { + throw new UnsupportedOperationException(); + } + + /** + * Adds a {@link JsonArray} from an array builder to the array at the specified position. + * Shifts the value currently at that position (if any) and any subsequent values + * to the right (adds one to their indices). Index starts with 0. + * + * @param index the position in the array + * @param builder the array builder + * @return this array builder + * @throws NullPointerException if the specified builder is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index > array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder add(int index, JsonArrayBuilder builder) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with the specified value at the + * specified position. + * + * @param index the position in the array + * @param value the JSON value + * @return this array builder + * @throws NullPointerException if the specified value is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, JsonValue value) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with the specified value as a + * {@link JsonString} at the specified position. + * + * @param index the position in the array + * @param value the string value + * @return this array builder + * @throws NullPointerException if the specified value is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, String value) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with the specified value as a + * {@link JsonNumber} at the specified position. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws NullPointerException if the specified value is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, BigDecimal value) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with the specified value as a + * {@link JsonNumber} at the specified position. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws NullPointerException if the specified value is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, BigInteger value) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with the specified value as a + * {@link JsonNumber} at the specified position. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, int value) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with the specified value as a + * {@link JsonNumber} at the specified position. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, long value) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with the specified value as a + * {@link JsonNumber} at the specified position. + * + * @param index the position in the array + * @param value the number value + * @return this array builder + * @throws NumberFormatException if the value is Not-a-Number (NaN) or + * infinity + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @see JsonNumber + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, double value) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with + * a {@link JsonValue#TRUE} or {@link JsonValue#FALSE} value + * at the specified position. + * + * @param index the position in the array + * @param value the boolean value + * @return this array builder + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, boolean value) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with + * a {@link JsonValue#NULL} value at the specified position. + * + * @param index the position in the array + * @return this array builder + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder setNull(int index) { + return set(index, JsonValue.NULL); + } + + /** + * Replaces a value in the array with the specified value as a + * {@link JsonObject} from an object builder at the specified position. + * + * @param index the position in the array + * @param builder the object builder + * @return this array builder + * @throws NullPointerException if the specified builder is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, JsonObjectBuilder builder) { + throw new UnsupportedOperationException(); + } + + /** + * Replaces a value in the array with the specified value as a + * {@link JsonArray} from an array builder at the specified position. + * + * @param index the position in the array + * @param builder the array builder + * @return this array builder + * @throws NullPointerException if the specified builder is null + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder set(int index, JsonArrayBuilder builder) { + throw new UnsupportedOperationException(); + } + + /** + * Remove the value in the array at the specified position. + * Shift any subsequent values to the left (subtracts one from their + * indices. + * + * @param index the position in the array + * @return this array builder + * @throws IndexOutOfBoundsException if the index is out of range + * {@code (index < 0 || index >= array size)} + * + * @since 1.1 + */ + default JsonArrayBuilder remove(int index) { + throw new UnsupportedOperationException(); + } + + /** + * Returns the current array. + * + * @return the current JSON array + */ + JsonArray build(); + +} +
diff --git a/api/src/main/java/jakarta/json/JsonBuilderFactory.java b/api/src/main/java/jakarta/json/JsonBuilderFactory.java new file mode 100644 index 0000000..eacfd1e --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonBuilderFactory.java
@@ -0,0 +1,133 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.util.Collection; +import java.util.Map; + +/** + * Factory to create {@link JsonObjectBuilder} and {@link JsonArrayBuilder} + * instances. If a factory instance is configured with some configuration, + * that would be used to configure the created builder instances. + * + * <p> + * {@code JsonObjectBuilder} and {@code JsonArrayBuilder} can also be created + * using {@link Json}'s methods. If multiple builder instances are created, + * then creating them using a builder factory is preferred. + * + * <p> + * <b>For example:</b> + * <pre> + * <code> + * JsonBuilderFactory factory = Json.createBuilderFactory(...); + * JsonArray value = factory.createArrayBuilder() + * .add(factory.createObjectBuilder() + * .add("type", "home") + * .add("number", "212 555-1234")) + * .add(factory.createObjectBuilder() + * .add("type", "fax") + * .add("number", "646 555-4567")) + * .build(); + * </code> + * </pre> + * + * <p> All the methods in this class are safe for use by multiple concurrent + * threads. + */ +public interface JsonBuilderFactory { + + /** + * Creates a {@code JsonObjectBuilder} instance that is used to build + * {@link JsonObject}. + * + * @return a JSON object builder + */ + JsonObjectBuilder createObjectBuilder(); + + /** + * Creates a {@code JsonObjectBuilder} instance, initialized with an object. + * + * @param object the initial object in the builder + * @return a JSON object builder + * @throws NullPointerException if specified object is {@code null} + * + * @since 1.1 + */ + default JsonObjectBuilder createObjectBuilder(JsonObject object) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a {@code JsonObjectBuilder} instance, initialized with the specified object. + * + * @param object the initial object in the builder + * @return a JSON object builder + * @throws NullPointerException if specified object is {@code null} + * + * @since 1.1 + */ + default JsonObjectBuilder createObjectBuilder(Map<String, Object> object) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a {@code JsonArrayBuilder} instance that is used to build + * {@link JsonArray} + * + * @return a JSON array builder + */ + JsonArrayBuilder createArrayBuilder(); + + /** + * Creates a {@code JsonArrayBuilder} instance, initialized with an array. + * + * @param array the initial array in the builder + * @return a JSON array builder + * @throws NullPointerException if specified array is {@code null} + * + * @since 1.1 + */ + default JsonArrayBuilder createArrayBuilder(JsonArray array) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a {@code JsonArrayBuilder} instance, + * initialized with the content of specified collection. + * + * @param collection the initial data for the builder + * @return a JSON array builder + * @throws NullPointerException if specified collection is {@code null} + * + * @since 1.1 + */ + default JsonArrayBuilder createArrayBuilder(Collection<?> collection) { + throw new UnsupportedOperationException(); + } + + /** + * Returns read-only map of supported provider specific configuration + * properties that are used to configure the created JSON builders. + * If there are any specified configuration properties that are not + * supported by the provider, they won't be part of the returned map. + * + * @return a map of supported provider specific properties that are used + * to configure the builders. The map be empty but not null. + */ + Map<String, ?> getConfigInUse(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonException.java b/api/src/main/java/jakarta/json/JsonException.java new file mode 100644 index 0000000..403cb75 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonException.java
@@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +/** + * <code>JsonException</code> indicates that some exception happened during + * JSON processing. + */ +public class JsonException extends RuntimeException { + + /** + * Constructs a new runtime exception with the specified detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public JsonException(String message) { + super(message); + } + + /** + * Constructs a new runtime exception with the specified detail message and + * cause. <p>Note that the detail message associated with + * {@code cause} is <i>not</i> automatically incorporated in + * this runtime exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A <code>null</code> value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + */ + public JsonException(String message, Throwable cause) { + super(message, cause); + } + +} +
diff --git a/api/src/main/java/jakarta/json/JsonMergePatch.java b/api/src/main/java/jakarta/json/JsonMergePatch.java new file mode 100644 index 0000000..07b64d8 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonMergePatch.java
@@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +/** + * <p>This interface represents an implementation of a JSON Merge Patch + * as defined by <a href="http://tools.ietf.org/html/rfc7396">RFC 7396</a>. + * </p> + * <p>A {@code JsonMergePatch} can be instantiated with {@link Json#createMergePatch(JsonValue)} + * by specifying the patch operations in a JSON Merge Patch or using {@link Json#createMergeDiff(JsonValue, JsonValue)} + * to create a JSON Merge Patch based on the difference between two {@code JsonValue}s. + * </p> + * The following illustrates both approaches. + * <p>1. Construct a JsonMergePatch with an existing JSON Merge Patch. + * <pre>{@code + * JsonValue contacts = ... ; // The target to be patched + * JsonValue patch = ... ; // JSON Merge Patch + * JsonMergePatch mergePatch = Json.createMergePatch(patch); + * JsonValue result = mergePatch.apply(contacts); + * } </pre> + * 2. Construct a JsonMergePatch from a difference between two {@code JsonValue}s. + * <pre>{@code + * JsonValue source = ... ; // The source object + * JsonValue target = ... ; // The modified object + * JsonMergePatch mergePatch = Json.createMergeDiff(source, target); // The diff between source and target in a Json Merge Patch format + * } </pre> + * + * @see <a href="http://tools.ietf.org/html/rfc7396">RFC 7396</a> + * + * @since 1.1 + */ +public interface JsonMergePatch { + + /** + * Applies the JSON Merge Patch to the specified {@code target}. + * The target is not modified by the patch. + * + * @param target the target to apply the merge patch + * @return the transformed target after the patch + */ + JsonValue apply(JsonValue target); + + /** + * Returns the {@code JsonMergePatch} as {@code JsonValue}. + * + * @return this {@code JsonMergePatch} as {@code JsonValue} + */ + JsonValue toJsonValue(); +}
diff --git a/api/src/main/java/jakarta/json/JsonNumber.java b/api/src/main/java/jakarta/json/JsonNumber.java new file mode 100644 index 0000000..6064cb1 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonNumber.java
@@ -0,0 +1,186 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * An immutable JSON number value. + * + * <p> + * Implementations may use a {@link BigDecimal} object to store the numeric + * value internally. + * The {@code BigDecimal} object can be constructed from the following types: + * <code>int</code> {@link BigDecimal#BigDecimal(int)}, + * <code>long</code> {@link BigDecimal#BigDecimal(long)}, + * <code>BigInteger</code> {@link BigDecimal#BigDecimal(BigInteger)}, + * <code>double</code> {@link BigDecimal#valueOf(double)}, and + * <code>String</code> {@link BigDecimal#BigDecimal(String)}. + * Some of the method semantics in this class are defined using the + * {@code BigDecimal} semantics. + */ +public interface JsonNumber extends JsonValue { + + /** + * Returns true if this JSON number is a integral number. This method + * semantics are defined using {@code bigDecimalValue().scale()}. If the + * scale is zero, then it is considered integral type. This integral type + * information can be used to invoke an appropriate accessor method to + * obtain a numeric value as in the following example: + * + * <pre> + * <code> + * JsonNumber num = ... + * if (num.isIntegral()) { + * num.longValue(); // or other methods to get integral value + * } else { + * num.doubleValue(); // or other methods to get decimal number value + * } + * </code> + * </pre> + * + * @return true if this number is a integral number, otherwise false + */ + boolean isIntegral(); + + /** + * Returns this JSON number as an {@code int}. Note that this conversion + * can lose information about the overall magnitude and precision of the + * number value as well as return a result with the opposite sign. + * + * @return an {@code int} representation of the JSON number + * @see java.math.BigDecimal#intValue() + */ + int intValue(); + + /** + * Returns this JSON number as an {@code int}. + * + * @return an {@code int} representation of the JSON number + * @throws ArithmeticException if the number has a nonzero fractional + * part or if it does not fit in an {@code int} + * @see java.math.BigDecimal#intValueExact() + */ + int intValueExact(); + + /** + * Returns this JSON number as a {@code long}. Note that this conversion + * can lose information about the overall magnitude and precision of the + * number value as well as return a result with the opposite sign. + * + * @return a {@code long} representation of the JSON number. + * @see java.math.BigDecimal#longValue() + */ + long longValue(); + + /** + * Returns this JSON number as a {@code long}. + * + * @return a {@code long} representation of the JSON number + * @throws ArithmeticException if the number has a non-zero fractional + * part or if it does not fit in a {@code long} + * @see java.math.BigDecimal#longValueExact() + */ + long longValueExact(); + + /** + * Returns this JSON number as a {@link BigInteger} object. This is a + * a convenience method for {@code bigDecimalValue().toBigInteger()}. + * Note that this conversion can lose information about the overall + * magnitude and precision of the number value as well as return a result + * with the opposite sign. + * + * @return a {@code BigInteger} representation of the JSON number. + * @see java.math.BigDecimal#toBigInteger() + */ + BigInteger bigIntegerValue(); + + /** + * Returns this JSON number as a {@link BigInteger} object. This is a + * convenience method for {@code bigDecimalValue().toBigIntegerExact()}. + * + * @return a {@link BigInteger} representation of the JSON number + * @throws ArithmeticException if the number has a nonzero fractional part + * @see java.math.BigDecimal#toBigIntegerExact() + */ + BigInteger bigIntegerValueExact(); + + /** + * Returns this JSON number as a {@code double}. This is a + * a convenience method for {@code bigDecimalValue().doubleValue()}. + * Note that this conversion can lose information about the overall + * magnitude and precision of the number value as well as return a result + * with the opposite sign. + * + * @return a {@code double} representation of the JSON number + * @see java.math.BigDecimal#doubleValue() + */ + double doubleValue(); + + /** + * Returns this JSON number as a {@link BigDecimal} object. + * + * @return a {@link BigDecimal} representation of the JSON number + */ + BigDecimal bigDecimalValue(); + + /** + * Returns this JSON number as a {@link Number} object. + * + * @return a {@link Number} representation of the JSON number + * + * @since 1.1 + */ + default Number numberValue() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a JSON text representation of the JSON number. The + * representation is equivalent to {@link BigDecimal#toString()}. + * + * @return JSON text representation of the number + */ + @Override + String toString(); + + /** + * Compares the specified object with this {@code JsonNumber} object for + * equality. Returns {@code true} if and only if the type of the specified + * object is also {@code JsonNumber} and their {@link #bigDecimalValue()} + * objects are <i>equal</i> + * + * @param obj the object to be compared for equality with + * this {@code JsonNumber} + * @return {@code true} if the specified object is equal to this + * {@code JsonNumber} + */ + @Override + boolean equals(Object obj); + + /** + * Returns the hash code value for this {@code JsonNumber} object. The + * hash code of a {@code JsonNumber} object is defined as the hash code of + * its {@link #bigDecimalValue()} object. + * + * @return the hash code value for this {@code JsonNumber} object + */ + @Override + int hashCode(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonObject.java b/api/src/main/java/jakarta/json/JsonObject.java new file mode 100644 index 0000000..61f1998 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonObject.java
@@ -0,0 +1,249 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.util.Map; + +/** + * {@code JsonObject} class represents an immutable JSON object value + * (an unordered collection of zero or more name/value pairs). + * It also provides unmodifiable map view to the JSON object + * name/value mappings. + * + * <p>A JsonObject instance can be created from an input source using + * {@link JsonReader#readObject()}. For example: + * <pre><code> + * JsonReader jsonReader = Json.createReader(...); + * JsonObject object = jsonReader.readObject(); + * jsonReader.close(); + * </code></pre> + * + * It can also be built from scratch using a {@link JsonObjectBuilder}. + * + * <p>For example 1: An empty JSON object can be built as follows: + * <pre><code> + * JsonObject object = Json.createObjectBuilder().build(); + * </code></pre> + * + * For example 2: The following JSON + * <pre><code> + * { + * "firstName": "John", "lastName": "Smith", "age": 25, + * "address" : { + * "streetAddress": "21 2nd Street", + * "city": "New York", + * "state": "NY", + * "postalCode": "10021" + * }, + * "phoneNumber": [ + * { "type": "home", "number": "212 555-1234" }, + * { "type": "fax", "number": "646 555-4567" } + * ] + * } + * </code></pre> + * can be built using : + * <pre><code> + * JsonObject value = Json.createObjectBuilder() + * .add("firstName", "John") + * .add("lastName", "Smith") + * .add("age", 25) + * .add("address", Json.createObjectBuilder() + * .add("streetAddress", "21 2nd Street") + * .add("city", "New York") + * .add("state", "NY") + * .add("postalCode", "10021")) + * .add("phoneNumber", Json.createArrayBuilder() + * .add(Json.createObjectBuilder() + * .add("type", "home") + * .add("number", "212 555-1234")) + * .add(Json.createObjectBuilder() + * .add("type", "fax") + * .add("number", "646 555-4567"))) + * .build(); + * </code></pre> + * + * {@code JsonObject} can be written to JSON as follows: + * <pre><code> + * JsonWriter writer = ... + * JsonObject obj = ...; + * writer.writeObject(obj); + * </code></pre> + * + * {@code JsonObject} values can be {@link JsonObject}, {@link JsonArray}, + * {@link JsonString}, {@link JsonNumber}, {@link JsonValue#TRUE}, + * {@link JsonValue#FALSE}, {@link JsonValue#NULL}. These values can be + * accessed using various accessor methods. + * + * <p>In the above example 2, "John" can be got using + * <pre><code> + * String firstName = object.getString("firstName"); + * </code></pre> + * + * This map object provides read-only access to the JSON object data, + * and attempts to modify the map, whether direct or via its collection + * views, result in an {@code UnsupportedOperationException}. + * + * <p>The map object's iteration ordering is based on the order in which + * name/value pairs are added to the corresponding builder or the order + * in which name/value pairs appear in the corresponding stream. + */ +public interface JsonObject extends JsonStructure, Map<String, JsonValue> { + + /** + * Returns the array value to which the specified name is mapped. + * This is a convenience method for {@code (JsonArray)get(name)} to + * get the value. + * + * @param name the name whose associated value is to be returned + * @return the array value to which the specified name is mapped, or + * {@code null} if this object contains no mapping for the name + * @throws ClassCastException if the value to which the specified name + * is mapped is not assignable to JsonArray type + */ + JsonArray getJsonArray(String name); + + /** + * Returns the object value to which the specified name is mapped. + * This is a convenience method for {@code (JsonObject)get(name)} to + * get the value. + * + * @param name the name whose associated value is to be returned + * @return the object value to which the specified name is mapped, or + * {@code null} if this object contains no mapping for the name + * @throws ClassCastException if the value to which the specified name + * is mapped is not assignable to JsonObject type + */ + JsonObject getJsonObject(String name); + + /** + * Returns the number value to which the specified name is mapped. + * This is a convenience method for {@code (JsonNumber)get(name)} to + * get the value. + * + * @param name the name whose associated value is to be returned + * @return the number value to which the specified name is mapped, or + * {@code null} if this object contains no mapping for the name + * @throws ClassCastException if the value to which the specified name + * is mapped is not assignable to JsonNumber type + */ + JsonNumber getJsonNumber(String name); + + /** + * Returns the string value to which the specified name is mapped. + * This is a convenience method for {@code (JsonString)get(name)} to + * get the value. + * + * @param name the name whose associated value is to be returned + * @return the string value to which the specified name is mapped, or + * {@code null} if this object contains no mapping for the name + * @throws ClassCastException if the value to which the specified name + * is mapped is not assignable to JsonString type + */ + JsonString getJsonString(String name); + + /** + * A convenience method for + * {@code getJsonString(name).getString()} + * + * @param name whose associated value is to be returned as String + * @return the String value to which the specified name is mapped + * @throws NullPointerException if the specified name doesn't have any + * mapping + * @throws ClassCastException if the value for specified name mapping + * is not assignable to JsonString + */ + String getString(String name); + + /** + * Returns the string value of the associated {@code JsonString} mapping + * for the specified name. If {@code JsonString} is found, then its + * {@link jakarta.json.JsonString#getString()} is returned. Otherwise, + * the specified default value is returned. + * + * @param name whose associated value is to be returned as String + * @param defaultValue a default value to be returned + * @return the string value of the associated mapping for the name, + * or the default value + */ + String getString(String name, String defaultValue); + + /** + * A convenience method for + * {@code getJsonNumber(name).intValue()} + * + * @param name whose associated value is to be returned as int + * @return the int value to which the specified name is mapped + * @throws NullPointerException if the specified name doesn't have any + * mapping + * @throws ClassCastException if the value for specified name mapping + * is not assignable to JsonNumber + */ + int getInt(String name); + + /** + * Returns the int value of the associated {@code JsonNumber} mapping + * for the specified name. If {@code JsonNumber} is found, then its + * {@link jakarta.json.JsonNumber#intValue()} is returned. Otherwise, + * the specified default value is returned. + * + * @param name whose associated value is to be returned as int + * @param defaultValue a default value to be returned + * @return the int value of the associated mapping for the name, + * or the default value + */ + int getInt(String name, int defaultValue); + + /** + * Returns the boolean value of the associated mapping for the specified + * name. If the associated mapping is JsonValue.TRUE, then returns true. + * If the associated mapping is JsonValue.FALSE, then returns false. + * + * @param name whose associated value is to be returned as boolean + * @return the boolean value to which the specified name is mapped + * @throws NullPointerException if the specified name doesn't have any + * mapping + * @throws ClassCastException if the value for specified name mapping + * is not assignable to JsonValue.TRUE or JsonValue.FALSE + */ + boolean getBoolean(String name); + + /** + * Returns the boolean value of the associated mapping for the specified + * name. If the associated mapping is JsonValue.TRUE, then returns true. + * If the associated mapping is JsonValue.FALSE, then returns false. + * Otherwise, the specified default value is returned. + * + * @param name whose associated value is to be returned as int + * @param defaultValue a default value to be returned + * @return the boolean value of the associated mapping for the name, + * or the default value + */ + boolean getBoolean(String name, boolean defaultValue); + + /** + * Returns {@code true} if the associated value for the specified name is + * {@code JsonValue.NULL}. + * + * @param name name whose associated value is checked + * @return return true if the associated value is {@code JsonValue.NULL}, + * otherwise false + * @throws NullPointerException if the specified name doesn't have any + * mapping + */ + boolean isNull(String name); + +}
diff --git a/api/src/main/java/jakarta/json/JsonObjectBuilder.java b/api/src/main/java/jakarta/json/JsonObjectBuilder.java new file mode 100644 index 0000000..b7fed79 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonObjectBuilder.java
@@ -0,0 +1,283 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * A builder for creating {@link JsonObject} models from scratch. This + * interface initializes an empty JSON object model and provides methods to add + * name/value pairs to the object model and to return the resulting object. + * The methods in this class can be chained to add multiple name/value pairs + * to the object. + * + * <p>The class {@link jakarta.json.Json} contains methods to create the builder + * object. The example code below shows how to build an empty {@code JsonObject} + * instance. + * <pre> + * <code> + * JsonObject object = Json.createObjectBuilder().build(); + * </code> + * </pre> + * + * <p>The class {@link JsonBuilderFactory} also contains methods to create + * {@code JsonObjectBuilder} instances. A factory instance can be used to create + * multiple builder instances with the same configuration. This the preferred + * way to create multiple instances. + * + * The example code below shows how to build a {@code JsonObject} model that + * represents the following JSON object: + * + * <pre> + * <code> + * { + * "firstName": "John", "lastName": "Smith", "age": 25, + * "address" : { + * "streetAddress": "21 2nd Street", + * "city": "New York", + * "state": "NY", + * "postalCode": "10021" + * }, + * "phoneNumber": [ + * { "type": "home", "number": "212 555-1234" }, + * { "type": "fax", "number": "646 555-4567" } + * ] + * } + * </code> + * </pre> + * + * <p>The code to create the object shown above is the following: + * + * <pre> + * <code> + * JsonBuilderFactory factory = Json.createBuilderFactory(config); + * JsonObject value = factory.createObjectBuilder() + * .add("firstName", "John") + * .add("lastName", "Smith") + * .add("age", 25) + * .add("address", factory.createObjectBuilder() + * .add("streetAddress", "21 2nd Street") + * .add("city", "New York") + * .add("state", "NY") + * .add("postalCode", "10021")) + * .add("phoneNumber", factory.createArrayBuilder() + * .add(factory.createObjectBuilder() + * .add("type", "home") + * .add("number", "212 555-1234")) + * .add(factory.createObjectBuilder() + * .add("type", "fax") + * .add("number", "646 555-4567"))) + * .build(); + * </code> + * </pre> + * + * <p>This class does <em>not</em> allow <code>null</code> to be used as a name or + * value while building the JSON object + * + * @see JsonArrayBuilder + */ +public interface JsonObjectBuilder { + + /** + * Adds a name/{@code JsonValue} pair to the JSON object associated with + * this object builder. If the object contains a mapping for the specified + * name, this method replaces the old value with the specified value. + * + * @param name name in the name/value pair + * @param value value in the name/value pair + * @return this object builder + * @throws NullPointerException if the specified name or value is null + */ + JsonObjectBuilder add(String name, JsonValue value); + + /** + * Adds a name/{@code JsonString} pair to the JSON object associated with + * this object builder. If the object contains a mapping for the specified + * name, this method replaces the old value with the specified value. + * + * @param name name in the name/value pair + * @param value value in the name/value pair + * @return this object builder + * @throws NullPointerException if the specified name or value is null + */ + JsonObjectBuilder add(String name, String value); + + /** + * Adds a name/{@code JsonNumber} pair to the JSON object associated with + * this object builder. If the object contains a mapping for the specified + * name, this method replaces the old value with the specified value. + * + * @param name name in the name/value pair + * @param value value in the name/value pair + * @return this object builder + * @throws NullPointerException if the specified name or value is null + * + * @see JsonNumber + */ + JsonObjectBuilder add(String name, BigInteger value); + + /** + * Adds a name/{@code JsonNumber} pair to the JSON object associated with + * this object builder. If the object contains a mapping for the specified + * name, this method replaces the old value with the specified value. + * + * @param name name in the name/value pair + * @param value value in the name/value pair + * @return this object builder + * @throws NullPointerException if the specified name or value is null + * + * @see JsonNumber + */ + JsonObjectBuilder add(String name, BigDecimal value); + + /** + * Adds a name/{@code JsonNumber} pair to the JSON object associated with + * this object builder. If the object contains a mapping for the specified + * name, this method replaces the old value with the specified value. + * + * @param name name in the name/value pair + * @param value value in the name/value pair + * @return this object builder + * @throws NullPointerException if the specified name is null + * + * @see JsonNumber + */ + JsonObjectBuilder add(String name, int value); + + /** + * Adds a name/{@code JsonNumber} pair to the JSON object associated with + * this object builder. If the object contains a mapping for the specified + * name, this method replaces the old value with the specified value. + * + * @param name name in the name/value pair + * @param value value in the name/value pair + * @return this object builder + * @throws NullPointerException if the specified name is null + * + * @see JsonNumber + */ + JsonObjectBuilder add(String name, long value); + + /** + * Adds a name/{@code JsonNumber} pair to the JSON object associated with + * this object builder. If the object contains a mapping for the specified + * name, this method replaces the old value with the specified value. + * + * @param name name in the name/value pair + * @param value value in the name/value pair + * @return this object builder + * @throws NumberFormatException if the value is Not-a-Number (NaN) or + * infinity + * @throws NullPointerException if the specified name is null + * + * @see JsonNumber + */ + JsonObjectBuilder add(String name, double value); + + /** + * Adds a name/{@code JsonValue#TRUE} or name/{@code JsonValue#FALSE} pair + * to the JSON object associated with this object builder. If the object + * contains a mapping for the specified name, this method replaces the old + * value with the specified value. + * + * @param name name in the name/value pair + * @param value value in the name/value pair + * @return this object builder + * @throws NullPointerException if the specified name is null + */ + JsonObjectBuilder add(String name, boolean value); + + /** + * Adds a name/{@code JsonValue#NULL} pair to the JSON object associated + * with this object builder where the value is {@code null}. + * If the object contains a mapping for the specified name, this method + * replaces the old value with {@code null}. + * + * @param name name in the name/value pair + * @return this object builder + * @throws NullPointerException if the specified name is null + */ + JsonObjectBuilder addNull(String name); + + /** + * Adds a name/{@code JsonObject} pair to the JSON object associated + * with this object builder. The value {@code JsonObject} is built from the + * specified object builder. If the object contains a mapping for the + * specified name, this method replaces the old value with the + * {@code JsonObject} from the specified object builder. + * + * @param name name in the name/value pair + * @param builder the value is the object associated with this builder + * @return this object builder + * @throws NullPointerException if the specified name or builder is null + */ + JsonObjectBuilder add(String name, JsonObjectBuilder builder); + + /** + * Adds a name/{@code JsonArray} pair to the JSON object associated with + * this object builder. The value {@code JsonArray} is built from the + * specified array builder. If the object contains a mapping for the + * specified name, this method replaces the old value with the + * {@code JsonArray} from the specified array builder. + * + * @param name the name in the name/value pair + * @param builder the value is the object array with this builder + * @return this object builder + * @throws NullPointerException if the specified name or builder is null + */ + JsonObjectBuilder add(String name, JsonArrayBuilder builder); + + /** + * Adds all name/value pairs in the JSON object associated with the specified + * object builder to the JSON object associated with this object builder. + * The newly added name/value pair will replace any existing name/value pair with + * the same name. + * + * @param builder the specified object builder + * @return this object builder + * @throws NullPointerException if the specified builder is null + * @since 1.1 + */ + default JsonObjectBuilder addAll(JsonObjectBuilder builder) { + throw new UnsupportedOperationException(); + } + + /** + * Remove the name/value pair from the JSON object associated with this + * object builder if it is present. + * + * @param name the name in the name/value pair to be removed + * @return this object builder + * @throws NullPointerException if the specified name is null + * @since 1.1 + */ + default JsonObjectBuilder remove(String name) { + throw new UnsupportedOperationException(); + } + + /** + * Returns the JSON object associated with this object builder. + * The iteration order for the {@code JsonObject} is based + * on the order in which name/value pairs are added to the object using + * this builder. + * + * @return JSON object that is being built + */ + JsonObject build(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonPatch.java b/api/src/main/java/jakarta/json/JsonPatch.java new file mode 100644 index 0000000..dea4e36 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonPatch.java
@@ -0,0 +1,139 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +/** + * <p>This interface represents an immutable implementation of a JSON Patch + * as defined by <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>. + * </p> + * <p>A {@code JsonPatch} can be instantiated with {@link Json#createPatch(JsonArray)} + * by specifying the patch operations in a JSON Patch. Alternately, it + * can also be constructed with a {@link JsonPatchBuilder}. + * </p> + * The following illustrates both approaches. + * <p>1. Construct a JsonPatch with a JSON Patch. + * <pre>{@code + * JsonArray contacts = ... // The target to be patched + * JsonArray patch = ... ; // JSON Patch + * JsonPatch jsonpatch = Json.createPatch(patch); + * JsonArray result = jsonpatch.apply(contacts); + * } </pre> + * 2. Construct a JsonPatch with JsonPatchBuilder. + * <pre>{@code + * JsonPatchBuilder builder = Json.createPatchBuilder(); + * JsonArray result = builder.add("/John/phones/office", "1234-567") + * .remove("/Amy/age") + * .build() + * .apply(contacts); + * } </pre> + * + * @see <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a> + * + * @since 1.1 + */ +public interface JsonPatch { + + /** + * This enum represents the list of valid JSON Patch operations + * as defined by <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>. + * + * @see <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a> + */ + enum Operation { + + /** + * "add" operation. + */ + ADD("add"), + + /** + * "remove" operation. + */ + REMOVE("remove"), + + /** + * "replace" operation. + */ + REPLACE("replace"), + + /** + * "move" operation. + */ + MOVE("move"), + + /** + * "copy" operation. + */ + COPY("copy"), + + /** + * "test" operation. + */ + TEST("test"); + + private final String operationName; + + private Operation(String operationName) { + this.operationName = operationName; + } + + /** + * Returns enum constant name as lower case string. + * + * @return lower case name of the enum constant + */ + public String operationName() { + return operationName; + } + + /** + * Returns the enum constant with the specified name. + * + * @param operationName {@code operationName} to convert to the enum constant. + * @return the enum constant for given {@code operationName} + * @throws JsonException if given {@code operationName} is not recognized + */ + public static Operation fromOperationName(String operationName) { + for (Operation op : values()) { + if (op.operationName().equalsIgnoreCase(operationName)) { + return op; + } + } + throw new JsonException("Illegal value for the operationName of the JSON patch operation: " + operationName); + } + } + + /** + * Applies the patch operations to the specified {@code target}. + * The target is not modified by the patch. + * + * @param <T> the target type, must be a subtype of {@link JsonStructure} + * @param target the target to apply the patch operations + * @return the transformed target after the patch + * @throws JsonException if the supplied JSON Patch is malformed or if + * it contains references to non-existing members + */ + <T extends JsonStructure> T apply(T target); + + /** + * Returns the {@code JsonPatch} as {@code JsonArray}. + * + * @return this {@code JsonPatch} as {@code JsonArray} + */ + JsonArray toJsonArray(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonPatchBuilder.java b/api/src/main/java/jakarta/json/JsonPatchBuilder.java new file mode 100644 index 0000000..0949839 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonPatchBuilder.java
@@ -0,0 +1,186 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +/** + * A builder for constructing a JSON Patch as defined by + * <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a> by adding + * JSON Patch operations incrementally. + * <p> + * The following illustrates the approach. + * <pre> + * JsonPatchBuilder builder = Json.createPatchBuilder(); + * JsonPatch patch = builder.add("/John/phones/office", "1234-567") + * .remove("/Amy/age") + * .build(); + * </pre> + * The result is equivalent to the following JSON Patch. + * <pre> + * [ + * {"op" = "add", "path" = "/John/phones/office", "value" = "1234-567"}, + * {"op" = "remove", "path" = "/Amy/age"} + * ] </pre> + * + * @see <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a> + * + * @since 1.1 + */ +public interface JsonPatchBuilder { + + /** + * Adds an "add" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder add(String path, JsonValue value); + + /** + * Adds an "add" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder add(String path, String value); + + /** + * Adds an "add" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder add(String path, int value); + + /** + * Adds an "add" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder add(String path, boolean value); + + /** + * Adds a "remove" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer. + * @return this JsonPatchBuilder + */ + JsonPatchBuilder remove(String path); + + /** + * Adds a "replace" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder replace(String path, JsonValue value); + + /** + * Adds a "replace" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer string. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder replace(String path, String value); + + /** + * Adds a "replace" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer string. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder replace(String path, int value); + + /** + * Adds a "replace" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer string. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder replace(String path, boolean value); + + /** + * Adds a "move" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer string. + * @param from the "from" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder move(String path, String from); + + /** + * Adds a "copy" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer string. + * @param from the "from" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder copy(String path, String from); + + /** + * Adds a "test" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer string. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder test(String path, JsonValue value); + + /** + * Adds a "test" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer string. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder test(String path, String value); + + /** + * Adds a "test" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer string. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder test(String path, int value); + + /** + * Adds a "test" JSON Patch operation. + * + * @param path the "path" member of the operation. Must be a valid escaped JSON-Pointer string. + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + JsonPatchBuilder test(String path, boolean value); + + + /** + * Returns the JSON Patch. + * + * @return a JSON Patch + */ + JsonPatch build(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonPointer.java b/api/src/main/java/jakarta/json/JsonPointer.java new file mode 100644 index 0000000..a42d8d3 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonPointer.java
@@ -0,0 +1,125 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +/** + * <p>This interface represents an immutable implementation of a JSON Pointer + * as defined by <a href="http://tools.ietf.org/html/rfc6901">RFC 6901</a>. + * </p> + * <p> A JSON Pointer, when applied to a target {@link JsonValue}, + * defines a reference location in the target.</p> + * <p> An empty JSON Pointer string defines a reference to the target itself.</p> + * <p> If the JSON Pointer string is non-empty, it must be a sequence + * of '/' prefixed tokens, and the target must either be a {@link JsonArray} + * or {@link JsonObject}. If the target is a {@code JsonArray}, the pointer + * defines a reference to an array element, and the last token specifies the index. + * If the target is a {@link JsonObject}, the pointer defines a reference to a + * name/value pair, and the last token specifies the name. + * </p> + * <p> The method {@link #getValue getValue()} returns the referenced value. + * Methods {@link #add add()}, {@link #replace replace()}, + * and {@link #remove remove()} execute operations specified in + * <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>. </p> + * + * @see <a href="http://tools.ietf.org/html/rfc6901">RFC 6901</a> + * @see <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a> + * + * @since 1.1 + */ +public interface JsonPointer { + + /** + * Adds or replaces a value at the referenced location in the specified + * {@code target} with the specified {@code value}. + * <ol> + * <li>If the reference is the target (empty JSON Pointer string), + * the specified {@code value}, which must be the same type as + * specified {@code target}, is returned.</li> + * <li>If the reference is an array element, the specified {@code value} is inserted + * into the array, at the referenced index. The value currently at that location, and + * any subsequent values, are shifted to the right (adds one to the indices). + * Index starts with 0. If the reference is specified with a "-", or if the + * index is equal to the size of the array, the value is appended to the array.</li> + * <li>If the reference is a name/value pair of a {@code JsonObject}, and the + * referenced value exists, the value is replaced by the specified {@code value}. + * If the value does not exist, a new name/value pair is added to the object.</li> + * </ol> + * + * @param <T> the target type, must be a subtype of {@link JsonValue} + * @param target the target referenced by this {@code JsonPointer} + * @param value the value to be added + * @return the transformed {@code target} after the value is added. + * @throws NullPointerException if {@code target} is {@code null} + * @throws JsonException if the reference is an array element and + * the index is out of range ({@code index < 0 || index > array size}), + * or if the pointer contains references to non-existing objects or arrays. + */ + <T extends JsonStructure> T add(T target, JsonValue value); + + /** + * Removes the value at the reference location in the specified {@code target}. + * + * @param <T> the target type, must be a subtype of {@link JsonValue} + * @param target the target referenced by this {@code JsonPointer} + * @return the transformed {@code target} after the value is removed. + * @throws NullPointerException if {@code target} is {@code null} + * @throws JsonException if the referenced value does not exist, + * or if the reference is the target. + */ + <T extends JsonStructure> T remove(T target); + + /** + * Replaces the value at the referenced location in the specified + * {@code target} with the specified {@code value}. + * + * @param <T> the target type, must be a subtype of {@link JsonValue} + * @param target the target referenced by this {@code JsonPointer} + * @param value the value to be stored at the referenced location + * @return the transformed {@code target} after the value is replaced. + * @throws NullPointerException if {@code target} is {@code null} + * @throws JsonException if the referenced value does not exist, + * or if the reference is the target. + */ + <T extends JsonStructure> T replace(T target, JsonValue value); + + /** + * Returns {@code true} if there is a value at the referenced location in the specified {@code target}. + * + * @param target the target referenced by this {@code JsonPointer} + * @return {@code true} if this pointer points to a value in a specified {@code target}. + */ + boolean containsValue(JsonStructure target); + + /** + * Returns the value at the referenced location in the specified {@code target}. + * + * @param target the target referenced by this {@code JsonPointer} + * @return the referenced value in the target. + * @throws NullPointerException if {@code target} is null + * @throws JsonException if the referenced value does not exist + */ + JsonValue getValue(JsonStructure target); + + /** + * Returns the string representation of this JSON Pointer. + * The value to be returned is an empty string or a sequence of '{@code /}' prefixed tokens. + * + * @return the valid escaped JSON Pointer string. + */ + @Override + String toString(); +}
diff --git a/api/src/main/java/jakarta/json/JsonReader.java b/api/src/main/java/jakarta/json/JsonReader.java new file mode 100644 index 0000000..b1192e6 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonReader.java
@@ -0,0 +1,133 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.io.Closeable; + +/** + * Reads a JSON {@link JsonObject object} or an {@link JsonArray array} + * structure from an input source. + * + * <p>The class {@link jakarta.json.Json} contains methods to create readers from + * input sources ({@link java.io.InputStream} and {@link java.io.Reader}). + * + * <p> + * The following example demonstrates how to read an empty JSON array from + * a string: + * <pre> + * <code> + * JsonReader jsonReader = Json.createReader(new StringReader("[]")); + * JsonArray array = jsonReader.readArray(); + * jsonReader.close(); + * </code> + * </pre> + * + * <p> + * The class {@link JsonReaderFactory} also contains methods to create + * {@code JsonReader} instances. A factory instance can be used to create + * multiple reader instances with the same configuration. This the preferred + * way to create multiple instances. A sample usage is shown in the following + * example: + * <pre> + * <code> + * JsonReaderFactory factory = Json.createReaderFactory(config); + * JsonReader reader1 = factory.createReader(...); + * JsonReader reader2 = factory.createReader(...); + * </code> + * </pre> + */ +public interface JsonReader extends /*Auto*/Closeable { + + /** + * Returns a JSON array or object that is represented in + * the input source. This method needs to be called + * only once for a reader instance. + * + * @return a JSON object or array + * @throws JsonException if a JSON object or array cannot + * be created due to i/o error (IOException would be + * cause of JsonException) + * @throws jakarta.json.stream.JsonParsingException if a JSON object or array + * cannot be created due to incorrect representation + * @throws IllegalStateException if read, readObject, readArray, + * readValue or close method is already called + */ + JsonStructure read(); + + /** + * Returns a JSON object that is represented in + * the input source. This method needs to be called + * only once for a reader instance. + * + * @return a JSON object + * @throws JsonException if a JSON object cannot + * be created due to i/o error (IOException would be + * cause of JsonException) + * @throws jakarta.json.stream.JsonParsingException if a JSON object cannot + * be created due to incorrect representation + * @throws IllegalStateException if read, readObject, readArray, + * readValue or close method is already called + */ + JsonObject readObject(); + + /** + * Returns a JSON array that is represented in + * the input source. This method needs to be called + * only once for a reader instance. + * + * @return a JSON array + * @throws JsonException if a JSON array cannot + * be created due to i/o error (IOException would be + * cause of JsonException) + * @throws jakarta.json.stream.JsonParsingException if a JSON array cannot + * be created due to incorrect representation + * @throws IllegalStateException if read, readObject, readArray, + * readValue or close method is already called + */ + JsonArray readArray(); + + /** + * Returns a JSON value that is represented in + * the input source. This method needs to be called + * only once for a reader instance. + * + * @return a JSON value + * @throws JsonException if a JSON value + * be created due to i/o error (IOException would be + * cause of JsonException) + * @throws jakarta.json.stream.JsonParsingException if a JSON value + * cannot be created due to incorrect representation + * @throws IllegalStateException if read, readObject, readArray, + * readValue or close method is already called + * + * @since 1.1 + */ + default JsonValue readValue() { + throw new UnsupportedOperationException(); + } + + /** + * Closes this reader and frees any resources associated with the + * reader. This method closes the underlying input source. + * + * @throws JsonException if an i/o error occurs (IOException would be + * cause of JsonException) + */ + @Override + void close(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonReaderFactory.java b/api/src/main/java/jakarta/json/JsonReaderFactory.java new file mode 100644 index 0000000..f0ff269 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonReaderFactory.java
@@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.io.InputStream; +import java.io.Reader; +import java.nio.charset.Charset; +import java.util.Map; + +/** + * Factory to create {@link jakarta.json.JsonReader} instances. If a factory + * instance is configured with some configuration, that would be + * used to configure the created reader instances. + * + * <p> + * {@link jakarta.json.JsonReader} can also be created using {@link Json}'s + * {@code createReader} methods. If multiple reader instances are created, + * then creating them using a reader factory is preferred. + * + * <p> + * <b>For example:</b> + * <pre> + * <code> + * JsonReaderFactory factory = Json.createReaderFactory(...); + * JsonReader reader1 = factory.createReader(...); + * JsonReader reader2 = factory.createReader(...); + * </code> + * </pre> + * + * <p> All the methods in this class are safe for use by multiple concurrent + * threads. + */ +public interface JsonReaderFactory { + + /** + * Creates a JSON reader from a character stream. The reader is configured + * with the factory configuration. + * + * @param reader a reader from which JSON is to be read + * @return a JSON reader + */ + JsonReader createReader(Reader reader); + + /** + * Creates a JSON reader from a byte stream. The character encoding of + * the stream is determined as described in + * <a href="http://tools.ietf.org/rfc/rfc7159.txt">RFC 7159</a>. + * The reader is configured with the factory configuration. + * + * @param in a byte stream from which JSON is to be read + * @return a JSON reader + */ + JsonReader createReader(InputStream in); + + /** + * Creates a JSON reader from a byte stream. The bytes of the stream + * are decoded to characters using the specified charset. The reader is + * configured with the factory configuration. + * + * @param in a byte stream from which JSON is to be read + * @param charset a charset + * @return a JSON reader + */ + JsonReader createReader(InputStream in, Charset charset); + + /** + * Returns read-only map of supported provider specific configuration + * properties that are used to configure the created JSON readers. + * If there are any specified configuration properties that are not + * supported by the provider, they won't be part of the returned map. + * + * @return a map of supported provider specific properties that are used + * to configure the readers. The map be empty but not null. + */ + Map<String, ?> getConfigInUse(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonString.java b/api/src/main/java/jakarta/json/JsonString.java new file mode 100644 index 0000000..ae833ef --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonString.java
@@ -0,0 +1,63 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +/** + * An immutable JSON string value. + */ +public interface JsonString extends JsonValue { + + /** + * Returns the JSON string value. + * + * @return a JSON string value + */ + String getString(); + + + /** + * Returns the char sequence for the JSON String value + * + * @return a char sequence for the JSON String value + */ + CharSequence getChars(); + + /** + * Compares the specified object with this {@code JsonString} for equality. + * Returns {@code true} if and only if the specified object is also a + * {@code JsonString}, and their {@link #getString()} objects are + * <i>equal</i>. + * + * @param obj the object to be compared for equality with this + * {@code JsonString} + * @return {@code true} if the specified object is equal to this + * {@code JsonString} + */ + @Override + boolean equals(Object obj); + + /** + * Returns the hash code value for this {@code JsonString} object. + * The hash code of a {@code JsonString} object is defined to be its + * {@link #getString()} object's hash code. + * + * @return the hash code value for this {@code JsonString} object + */ + @Override + int hashCode(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonStructure.java b/api/src/main/java/jakarta/json/JsonStructure.java new file mode 100644 index 0000000..92c9c8d --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonStructure.java
@@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +/** + * Super type for the two structured types in JSON ({@link JsonObject object}s + * and {@link JsonArray array}s). + */ +public interface JsonStructure extends JsonValue { + + /** + * Get the value referenced by the provided JSON Pointer in the JsonStructure. + * + * @param jsonPointer the JSON Pointer + * @return the {@code JsonValue} at the referenced location + * @throws JsonException if the JSON Pointer is malformed, or if it references + * a non-existing member or value. + * + * @since 1.1 + */ + default public JsonValue getValue(String jsonPointer) { + return Json.createPointer(jsonPointer).getValue(this); + } +}
diff --git a/api/src/main/java/jakarta/json/JsonValue.java b/api/src/main/java/jakarta/json/JsonValue.java new file mode 100644 index 0000000..4dec772 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonValue.java
@@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +/** + * <code>JsonValue</code> represents an immutable JSON value. + * + * + * <p>A JSON value is one of the following: + * an object ({@link JsonObject}), an array ({@link JsonArray}), + * a number ({@link JsonNumber}), a string ({@link JsonString}), + * {@code true} ({@link JsonValue#TRUE JsonValue.TRUE}), {@code false} + * ({@link JsonValue#FALSE JsonValue.FALSE}), + * or {@code null} ({@link JsonValue#NULL JsonValue.NULL}). + */ +public interface JsonValue { + + /** + * The empty JSON object. + * + * @since 1.1 + */ + static final JsonObject EMPTY_JSON_OBJECT = new EmptyObject(); + + /** + * The empty JSON array. + * + * @since 1.1 + */ + static final JsonArray EMPTY_JSON_ARRAY = new EmptyArray(); + + /** + * Indicates the type of a {@link JsonValue} object. + */ + enum ValueType { + /** + * JSON array. + */ + ARRAY, + + /** + * JSON object. + */ + OBJECT, + + /** + * JSON string. + */ + STRING, + + /** + * JSON number. + */ + NUMBER, + + /** + * JSON true. + */ + TRUE, + + /** + * JSON false. + */ + FALSE, + + /** + * JSON null. + */ + NULL + } + + /** + * JSON null value. + */ + static final JsonValue NULL = new JsonValueImpl(ValueType.NULL); + + /** + * JSON true value. + */ + static final JsonValue TRUE = new JsonValueImpl(ValueType.TRUE); + + /** + * JSON false value. + */ + static final JsonValue FALSE = new JsonValueImpl(ValueType.FALSE); + + /** + * Returns the value type of this JSON value. + * + * @return JSON value type + */ + ValueType getValueType(); + + /** + * Return the JsonValue as a JsonObject + * + * @return the JsonValue as a JsonObject + * @throws ClassCastException if the JsonValue is not a JsonObject + * + * @since 1.1 + */ + default JsonObject asJsonObject() { + return JsonObject.class.cast(this); + } + + /** + * Return the JsonValue as a JsonArray + * + * @return the JsonValue as a JsonArray + * @throws ClassCastException if the JsonValue is not a JsonArray + * + * @since 1.1 + */ + default JsonArray asJsonArray() { + return JsonArray.class.cast(this); + } + + /** + * Returns JSON text for this JSON value. + * + * @return JSON text + */ + @Override + String toString(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonValueImpl.java b/api/src/main/java/jakarta/json/JsonValueImpl.java new file mode 100644 index 0000000..16d193b --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonValueImpl.java
@@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.io.Serializable; + +/** + * Private implementation of {@link JsonValue} for simple {@link ValueType}s + * allowing their usage in constants which are better to implement {@link Serializable}. + * + * @author Lukas Jungmann + */ +final class JsonValueImpl implements JsonValue, Serializable { + + private final ValueType valueType; + + JsonValueImpl(ValueType valueType) { + this.valueType = valueType; + } + + /** + * Returns the value type of this JSON value. + * + * @return JSON value type + */ + @Override + public ValueType getValueType() { + return valueType; + } + + /** + * Compares the specified object with this {@link JsonValue} + * object for equality. Returns {@code true} if and only if the + * specified object is also a JsonValue, and their + * {@link #getValueType()} objects are <i>equal</i>. + * + * @param obj the object to be compared for equality with this JsonValue + * @return {@code true} if the specified object is equal to this + * JsonValue + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof JsonValue) { + return getValueType().equals(((JsonValue) obj).getValueType()); + } + return false; + } + + /** + * Returns the hash code value for this {@link JsonValue} object. + * The hash code of the {@link JsonValue} object is defined to be + * its {@link #getValueType()} object's hash code. + * + * @return the hash code value for this {@link JsonValue} object + */ + @Override + public int hashCode() { + return valueType.hashCode(); + } + + @Override + public String toString() { + return valueType.name().toLowerCase(); + } + +}
diff --git a/api/src/main/java/jakarta/json/JsonWriter.java b/api/src/main/java/jakarta/json/JsonWriter.java new file mode 100644 index 0000000..b20b607 --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonWriter.java
@@ -0,0 +1,123 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.io.Closeable; + +/** + * Writes a JSON {@link JsonObject object} or {@link JsonArray array} structure + * to an output source. + * + * <p>The class {@link jakarta.json.Json} contains methods to create writers from + * output sources ({@link java.io.OutputStream} and {@link java.io.Writer}). + * + * <p> + * The following example demonstrates how write an empty JSON object: + * <pre> + * <code> + * JsonWriter jsonWriter = Json.createWriter(...); + * jsonWriter.writeObject(Json.createObjectBuilder().build()); + * jsonWriter.close(); + * </code> + * </pre> + * + * <p> + * The class {@link JsonWriterFactory} also contains methods to create + * {@code JsonWriter} instances. A factory instance can be used to create + * multiple writer instances with the same configuration. This the preferred + * way to create multiple instances. A sample usage is shown in the following + * example: + * <pre> + * <code> + * JsonWriterFactory factory = Json.createWriterFactory(config); + * JsonWriter writer1 = factory.createWriter(...); + * JsonWriter writer2 = factory.createWriter(...); + * </code> + * </pre> + */ +public interface JsonWriter extends /*Auto*/Closeable { + + /** + * Writes the specified JSON {@link JsonArray array} to the output + * source. This method needs to be called only once for a writer instance. + * + * @param array JSON array that is to be written to the output source + * @throws JsonException if the specified JSON object cannot be + * written due to i/o error (IOException would be cause of + * JsonException) + * @throws IllegalStateException if writeArray, writeObject, write or close + * method is already called + */ + void writeArray(JsonArray array); + + /** + * Writes the specified JSON {@link JsonObject object} to the output + * source. This method needs to be called only once for a writer instance. + * + * @param object JSON object that is to be written to the output source + * @throws JsonException if the specified JSON object cannot be + * written due to i/o error (IOException would be cause of JsonException) + * @throws IllegalStateException if writeArray, writeObject, write or close + * method is already called + */ + void writeObject(JsonObject object); + + /** + * Writes the specified JSON {@link JsonObject object} or + * {@link JsonArray array} to the output source. This method needs + * to be called only once for a writer instance. + * + * @param value JSON array or object that is to be written to the output + * source + * @throws JsonException if the specified JSON object cannot be + * written due to i/o error (IOException would be cause of + * JsonException) + * @throws IllegalStateException if writeArray, writeObject, write + * or close method is already called + */ + void write(JsonStructure value); + + /** + * Closes this JSON writer and frees any resources associated with the + * writer. This method closes the underlying output source. + * + * @throws JsonException if an i/o error occurs (IOException would be + * cause of JsonException) + */ + + /** + * Writes the specified {@link JsonValue} to the output source. + * method needs to be called only once for a write instance. + * + * @param value a {@code JsonValue} to be written to the output + * source + * @throws JsonException if the specified JSON object cannot be + * written due to i/o error (IOException would be cause of + * JsonException) + * @throws IllegalStateException if writeArray, writeObject, write + * or close method is already called + * + * @since 1.1 + */ + default void write(JsonValue value) { + throw new UnsupportedOperationException(); + } + + @Override + void close(); + +}
diff --git a/api/src/main/java/jakarta/json/JsonWriterFactory.java b/api/src/main/java/jakarta/json/JsonWriterFactory.java new file mode 100644 index 0000000..49fe62f --- /dev/null +++ b/api/src/main/java/jakarta/json/JsonWriterFactory.java
@@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json; + +import java.io.OutputStream; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.Map; + +/** + * Factory to create {@link jakarta.json.JsonWriter} instances. If a factory + * instance is configured with some configuration, that would be + * used to configure the created writer instances. + * + * <p> + * {@link jakarta.json.JsonWriter} can also be created using {@link Json}'s + * {@code createWriter} methods. If multiple writer instances are created, + * then creating them using a writer factory is preferred. + * + * <p> + * <b>For example:</b> + * <pre> + * <code> + * JsonWriterFactory factory = Json.createWriterFactory(...); + * JsonWriter writer1 = factory.createWriter(...); + * JsonWriter writer2 = factory.createWriter(...); + * </code> + * </pre> + * + * <p> All the methods in this class are safe for use by multiple concurrent + * threads. + */ +public interface JsonWriterFactory { + + /** + * Creates a JSON writer to write a JSON {@link JsonObject object} or + * {@link JsonArray array} structure to the specified character stream. + * The writer is configured with the factory configuration. + * + * @param writer to which JSON object or array is written + * @return a JSON writer + */ + JsonWriter createWriter(Writer writer); + + /** + * Creates a JSON writer to write a JSON {@link JsonObject object} or + * {@link JsonArray array} structure to the specified byte stream. + * Characters written to the stream are encoded into bytes using UTF-8 + * encoding. The writer is configured with the factory configuration. + * + * @param out to which JSON object or array is written + * @return a JSON writer + */ + JsonWriter createWriter(OutputStream out); + + /** + * Creates a JSON writer to write a JSON {@link JsonObject object} or + * {@link JsonArray array} structure to the specified byte stream. + * Characters written to the stream are encoded into bytes using the + * specified charset. The writer is configured with the factory + * configuration. + * + * @param out to which JSON object or array is written + * @param charset a charset + * @return a JSON writer + */ + JsonWriter createWriter(OutputStream out, Charset charset); + + /** + * Returns read-only map of supported provider specific configuration + * properties that are used to configure the created JSON writer objects. + * If there are any specified configuration properties that are not + * supported by the provider, they won't be part of the returned map. + * + * @return a map of supported provider specific properties that are used + * to configure the created writers. The map may be empty but not null. + */ + Map<String, ?> getConfigInUse(); + +}
diff --git a/api/src/main/java/jakarta/json/package-info.java b/api/src/main/java/jakarta/json/package-info.java new file mode 100644 index 0000000..a5906ec --- /dev/null +++ b/api/src/main/java/jakarta/json/package-info.java
@@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/** + * Provides an object model API to process <a href="http://json.org/">JSON</a>. + * + * <p>The object model API is a high-level API that provides immutable object + * models for JSON object and array structures. These JSON structures are + * represented as object models using the Java types {@link jakarta.json.JsonObject} + * and {@link jakarta.json.JsonArray}. The interface {@code jakarta.json.JsonObject} provides + * a {@link java.util.Map} view to access the unordered collection of zero or + * more name/value pairs from the model. Similarly, the interface + * {@code JsonArray} provides a {@link java.util.List} view to access the + * ordered sequence of zero or more values from the model. + * + * <p>The object model API uses builder patterns to create and modify + * these object models. The classes {@link jakarta.json.JsonObjectBuilder} and + * {@link jakarta.json.JsonArrayBuilder} provide methods to create and modify models + * of type {@code JsonObject} and {@code JsonArray} respectively. + * + * <p>These object models can also be created from an input source using + * the class {@link jakarta.json.JsonReader}. Similarly, these object models + * can be written to an output source using the class {@link jakarta.json.JsonWriter}. + * <p> + * This package includes several classes that implement other JSON related + * standards: <a href="http://tools.ietf.org/html/rfc6901">JSON Pointer</a>, + * <a Href="http://tools.ietf.org/html/rfc6902">JSON Patch</a>, and + * <a Href="http://tools.ietf.org/html/rfc7396">JSON Merge Patch</a>. + * They can be used to retrieve, transform or manipulate values in an + * object model. + */ +package jakarta.json;
diff --git a/api/src/main/java/jakarta/json/spi/JsonProvider.java b/api/src/main/java/jakarta/json/spi/JsonProvider.java new file mode 100644 index 0000000..ea56275 --- /dev/null +++ b/api/src/main/java/jakarta/json/spi/JsonProvider.java
@@ -0,0 +1,480 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json.spi; + +import jakarta.json.*; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonGeneratorFactory; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParserFactory; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.ServiceLoader; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Optional; + +/** + * Service provider for JSON processing objects. + * + * <p>All the methods in this class are safe for use by multiple concurrent + * threads. + * + * @see ServiceLoader + */ +public abstract class JsonProvider { + + /** + * A constant representing the name of the default + * {@code JsonProvider} implementation class. + */ + private static final String DEFAULT_PROVIDER + = "org.glassfish.json.JsonProviderImpl"; + + protected JsonProvider() { + } + + /** + * Creates a JSON provider object. The provider is loaded using the + * {@link ServiceLoader#load(Class)} method. If there are no available + * service providers, this method returns the default service provider. + * Users are recommended to cache the result of this method. + * + * @see ServiceLoader + * @return a JSON provider + */ + public static JsonProvider provider() { + ServiceLoader<JsonProvider> loader = ServiceLoader.load(JsonProvider.class); + Iterator<JsonProvider> it = loader.iterator(); + if (it.hasNext()) { + return it.next(); + } + try { + Class<?> clazz = Class.forName(DEFAULT_PROVIDER); + return (JsonProvider) clazz.newInstance(); + } catch (ClassNotFoundException x) { + throw new JsonException( + "Provider " + DEFAULT_PROVIDER + " not found", x); + } catch (Exception x) { + throw new JsonException( + "Provider " + DEFAULT_PROVIDER + " could not be instantiated: " + x, + x); + } + } + + /** + * Creates a JSON parser from a character stream. + * + * @param reader i/o reader from which JSON is to be read + * @return a JSON parser + */ + public abstract JsonParser createParser(Reader reader); + + /** + * Creates a JSON parser from the specified byte stream. + * The character encoding of the stream is determined + * as defined in <a href="http://tools.ietf.org/rfc/rfc7159.txt">RFC 7159 + * </a>. + * + * @param in i/o stream from which JSON is to be read + * @throws JsonException if encoding cannot be determined + * or i/o error (IOException would be cause of JsonException) + * @return a JSON parser + */ + public abstract JsonParser createParser(InputStream in); + + /** + * Creates a parser factory for creating {@link JsonParser} instances. + * + * @return a JSON parser factory + * + public abstract JsonParserFactory createParserFactory(); + */ + + /** + * Creates a parser factory for creating {@link JsonParser} instances. + * The factory is configured with the specified map of + * provider specific configuration properties. Provider implementations + * should ignore any unsupported configuration properties specified in + * the map. + * + * @param config a map of provider specific properties to configure the + * JSON parsers. The map may be empty or null + * @return a JSON parser factory + */ + public abstract JsonParserFactory createParserFactory(Map<String, ?> config); + + /** + * Creates a JSON generator for writing JSON text to a character stream. + * + * @param writer a i/o writer to which JSON is written + * @return a JSON generator + */ + public abstract JsonGenerator createGenerator(Writer writer); + + /** + * Creates a JSON generator for writing JSON text to a byte stream. + * + * @param out i/o stream to which JSON is written + * @return a JSON generator + */ + public abstract JsonGenerator createGenerator(OutputStream out); + + /** + * Creates a generator factory for creating {@link JsonGenerator} instances. + * + * @return a JSON generator factory + * + public abstract JsonGeneratorFactory createGeneratorFactory(); + */ + + /** + * Creates a generator factory for creating {@link JsonGenerator} instances. + * The factory is configured with the specified map of provider specific + * configuration properties. Provider implementations should + * ignore any unsupported configuration properties specified in the map. + * + * @param config a map of provider specific properties to configure the + * JSON generators. The map may be empty or null + * @return a JSON generator factory + */ + public abstract JsonGeneratorFactory createGeneratorFactory(Map<String, ?> config); + + /** + * Creates a JSON reader from a character stream. + * + * @param reader a reader from which JSON is to be read + * @return a JSON reader + */ + public abstract JsonReader createReader(Reader reader); + + /** + * Creates a JSON reader from a byte stream. The character encoding of + * the stream is determined as described in + * <a href="http://tools.ietf.org/rfc/rfc7159.txt">RFC 7159</a>. + * + * @param in a byte stream from which JSON is to be read + * @return a JSON reader + */ + public abstract JsonReader createReader(InputStream in); + + /** + * Creates a JSON writer to write a + * JSON {@link JsonObject object} or {@link JsonArray array} + * structure to the specified character stream. + * + * @param writer to which JSON object or array is written + * @return a JSON writer + */ + public abstract JsonWriter createWriter(Writer writer); + + /** + * Creates a JSON writer to write a + * JSON {@link JsonObject object} or {@link JsonArray array} + * structure to the specified byte stream. Characters written to + * the stream are encoded into bytes using UTF-8 encoding. + * + * @param out to which JSON object or array is written + * @return a JSON writer + */ + public abstract JsonWriter createWriter(OutputStream out); + + /** + * Creates a writer factory for creating {@link JsonWriter} objects. + * The factory is configured with the specified map of provider specific + * configuration properties. Provider implementations should ignore any + * unsupported configuration properties specified in the map. + * + * @param config a map of provider specific properties to configure the + * JSON writers. The map may be empty or null + * @return a JSON writer factory + */ + public abstract JsonWriterFactory createWriterFactory(Map<String,?> config); + + /** + * Creates a reader factory for creating {@link JsonReader} objects. + * The factory is configured with the specified map of provider specific + * configuration properties. Provider implementations should ignore any + * unsupported configuration properties specified in the map. + * + * @param config a map of provider specific properties to configure the + * JSON readers. The map may be empty or null + * @return a JSON reader factory + */ + public abstract JsonReaderFactory createReaderFactory(Map<String,?> config); + + /** + * Creates a JSON object builder. + * + * @return a JSON object builder + */ + public abstract JsonObjectBuilder createObjectBuilder(); + + /** + * Creates a JSON object builder, initialized with the specified object. + * + * @param object the initial JSON object in the builder + * @return a JSON object builder + * + * @since 1.1 + */ + public JsonObjectBuilder createObjectBuilder(JsonObject object) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JSON object builder, initialized with the data from specified {@code map}. + * If the @{code map} contains {@link Optional}s then resulting JSON object builder + * contains the key from the {@code map} only if the {@link Optional} is not empty. + * + * @param map the initial object in the builder + * @return a JSON object builder + * @exception IllegalArgumentException if the value from the {@code map} cannot be converted + * to the corresponding {@link JsonValue} + * + * @since 1.1 + */ + public JsonObjectBuilder createObjectBuilder(Map<String, Object> map) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JSON array builder. + * + * @return a JSON array builder + */ + public abstract JsonArrayBuilder createArrayBuilder(); + + /** + * Creates a JSON array builder, initialized with the specified array. + * + * @param array the initial JSON array in the builder + * @return a JSON array builder + * + * @since 1.1 + */ + public JsonArrayBuilder createArrayBuilder(JsonArray array) { + throw new UnsupportedOperationException(); + } + + /** + * Creates JSON Pointer (<a href="http://tools.ietf.org/html/rfc6901">RFC 6901</a>) + * from given {@code jsonPointer} string. + * <ul> + * <li>An empty {@code jsonPointer} string defines a reference to the target itself.</li> + * <li>If the {@code jsonPointer} string is non-empty, it must be a sequence of '{@code /}' prefixed tokens.</li> + * </ul> + * + * @param jsonPointer the JSON Pointer string + * @throws NullPointerException if {@code jsonPointer} is {@code null} + * @throws JsonException if {@code jsonPointer} is not a valid JSON Pointer + * @return a JSON Pointer + * + * @since 1.1 + */ + public JsonPointer createPointer(String jsonPointer) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JSON Patch builder (<a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>). + * + * @return a JSON Patch builder + * + * @since 1.1 + */ + public JsonPatchBuilder createPatchBuilder() { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JSON Patch builder + * (<a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>), + * initialized with the specified operations. + * + * @param array the initial patch operations + * @return a JSON Patch builder + * + * @since 1.1 + */ + public JsonPatchBuilder createPatchBuilder(JsonArray array) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JSON Patch (<a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>) + * from the specified operations. + * + * @param array patch operations + * @return a JSON Patch + * + * @since 1.1 + */ + public JsonPatch createPatch(JsonArray array) { + throw new UnsupportedOperationException(); + } + + /** + * Generates a JSON Patch (<a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>) + * from the source and target {@code JsonStructure}. + * The generated JSON Patch need not be unique. + * + * @param source the source + * @param target the target, must be the same type as the source + * @return a JSON Patch which when applied to the source, yields the target + * + * @since 1.1 + */ + public JsonPatch createDiff(JsonStructure source, JsonStructure target) { + throw new UnsupportedOperationException(); + } + + /** + * Creates JSON Merge Patch (<a href="http://tools.ietf.org/html/rfc7396">RFC 7396</a>) + * from specified {@code JsonValue}. + * + * @param patch the patch + * @return a JSON Merge Patch + * + * @since 1.1 + */ + public JsonMergePatch createMergePatch(JsonValue patch) { + throw new UnsupportedOperationException(); + } + + /** + * Generates a JSON Merge Patch (<a href="http://tools.ietf.org/html/rfc7396">RFC 7396</a>) + * from the source and target {@code JsonValue}s + * which when applied to the {@code source}, yields the {@code target}. + * + * @param source the source + * @param target the target + * @return a JSON Merge Patch + * + * @since 1.1 + */ + public JsonMergePatch createMergeDiff(JsonValue source, JsonValue target) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JSON array builder, initialized with the content of specified {@code collection}. + * If the @{code collection} contains {@link Optional}s then resulting JSON array builder + * contains the value from the {@code collection} only if the {@link Optional} is not empty. + * + * @param collection the initial data for the builder + * @return a JSON array builder + * @exception IllegalArgumentException if the value from the {@code collection} cannot be converted + * to the corresponding {@link JsonValue} + * + * @since 1.1 + */ + public JsonArrayBuilder createArrayBuilder(Collection<?> collection) { + throw new UnsupportedOperationException(); + } + + + /** + * Creates a builder factory for creating {@link JsonArrayBuilder} + * and {@link JsonObjectBuilder} objects. + * The factory is configured with the specified map of provider specific + * configuration properties. Provider implementations should ignore any + * unsupported configuration properties specified in the map. + * + * @param config a map of provider specific properties to configure the + * JSON builders. The map may be empty or null + * @return a JSON builder factory + */ + public abstract JsonBuilderFactory createBuilderFactory(Map<String,?> config); + + /** + * Creates a JsonString. + * + * @param value a JSON string + * @return the JsonString for the string + * + * @since 1.1 + */ + public JsonString createValue(String value) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public JsonNumber createValue(int value) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public JsonNumber createValue(long value) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public JsonNumber createValue(double value) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public JsonNumber createValue(BigDecimal value) { + throw new UnsupportedOperationException(); + } + + /** + * Creates a JsonNumber. + * + * @param value a JSON number + * @return the JsonNumber for the number + * + * @since 1.1 + */ + public JsonNumber createValue(BigInteger value) { + throw new UnsupportedOperationException(); + } +}
diff --git a/api/src/main/java/jakarta/json/spi/package-info.java b/api/src/main/java/jakarta/json/spi/package-info.java new file mode 100644 index 0000000..57c892b --- /dev/null +++ b/api/src/main/java/jakarta/json/spi/package-info.java
@@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/** + * Service Provider Interface (SPI) to plug in implementations for + * JSON processing objects. + * + * <p> {@link jakarta.json.spi.JsonProvider JsonProvider} is an abstract class + * that provides a service for creating JSON processing instances. + * A <i>service provider</i> for {@code JsonProvider} provides an + * specific implementation by subclassing and implementing the methods in + * {@code JsonProvider}. This enables using custom, efficient JSON processing + * implementations (for e.g. parser and generator) other than the default ones. + * + * <p>The API locates and loads providers using {@link java.util.ServiceLoader}. + * + * @since JSON Processing 1.0 + */ +package jakarta.json.spi;
diff --git a/api/src/main/java/jakarta/json/stream/JsonCollectors.java b/api/src/main/java/jakarta/json/stream/JsonCollectors.java new file mode 100644 index 0000000..2a1678d --- /dev/null +++ b/api/src/main/java/jakarta/json/stream/JsonCollectors.java
@@ -0,0 +1,160 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json.stream; + +import java.util.Map; +import java.util.HashMap; +import java.util.stream.Collector; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.BiConsumer; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; +import jakarta.json.JsonException; + +/** + * This class contains some implementations of {@code java.util.stream.Collector} for accumulating + * {@link JsonValue}s into {@link JsonArray} and {@link JsonObject}. + * + * @since 1.1 + */ + +public final class JsonCollectors { + + private JsonCollectors() { + } + + /** + * Constructs a {@code java.util.stream.Collector} that accumulates the input {@code JsonValue} + * elements into a {@code JsonArray}. + * + * @return the constructed Collector + */ + public static Collector<JsonValue, JsonArrayBuilder, JsonArray> toJsonArray() { + return Collector.of( + Json::createArrayBuilder, + JsonArrayBuilder::add, + JsonArrayBuilder::addAll, + JsonArrayBuilder::build); + } + + /** + * Constructs a {@code java.util.stream.Collector} that accumulates the input {@code Map.Entry<String,JsonValue>} + * elements into a {@code JsonObject}. + * + * @return the constructed Collector + */ + public static Collector<Map.Entry<String, JsonValue>, JsonObjectBuilder, JsonObject> toJsonObject() { + return Collector.of( + Json::createObjectBuilder, + (JsonObjectBuilder b, Map.Entry<String, JsonValue> v) -> b.add(v.getKey(), v.getValue()), + JsonObjectBuilder::addAll, + JsonObjectBuilder::build); + } + + /** + * Constructs a {@code java.util.stream.Collector} that accumulates the input {@code JsonValue} + * elements into a {@code JsonObject}. The name/value pairs of the {@code JsonObject} are computed + * by applying the provided mapping functions. + * + * @param keyMapper a mapping function to produce names. + * @param valueMapper a mapping function to produce values + * @return the constructed Collector + */ + public static Collector<JsonValue, JsonObjectBuilder, JsonObject> + toJsonObject(Function<JsonValue, String> keyMapper, + Function<JsonValue, JsonValue> valueMapper) { + return Collector.of( + Json::createObjectBuilder, + (b, v) -> b.add(keyMapper.apply(v), valueMapper.apply(v)), + JsonObjectBuilder::addAll, + JsonObjectBuilder::build, + Collector.Characteristics.UNORDERED); + } + + /** + * Constructs a {@code java.util.stream.Collector} that implements a "group by" operation on the + * input {@code JsonValue} elements. A classifier function maps the input {@code JsonValue}s to keys, and + * the {@code JsonValue}s are partitioned into groups according to the value of the key. + * A reduction operation is performed on the {@code JsonValue}s in each group, using the + * downstream {@code Collector}. For each group, the key and the results of the reduction operation + * become the name/value pairs of the resultant {@code JsonObject}. + * + * @param <T> the intermediate accumulation {@code JsonArrayBuilder} of the downstream collector + * @param classifier a function mapping the input {@code JsonValue}s to a String, producing keys + * @param downstream a {@code Collector} that implements a reduction operation on the + * {@code JsonValue}s in each group. + * @return the constructed {@code Collector} + */ + public static <T extends JsonArrayBuilder> Collector<JsonValue, Map<String, T>, JsonObject> + groupingBy(Function<JsonValue, String> classifier, + Collector<JsonValue, T, JsonArray> downstream) { + + BiConsumer<Map<String, T>, JsonValue> accumulator = + (map, value) -> { + String key = classifier.apply(value); + if (key == null) { + throw new JsonException("element cannot be mapped to a null key"); + } + // Build a map of key to JsonArrayBuilder + T arrayBuilder = + map.computeIfAbsent(key, v->downstream.supplier().get()); + // Add elements from downstream Collector to the arrayBuilder. + downstream.accumulator().accept(arrayBuilder, value); + }; + Function<Map<String, T>, JsonObject> finisher = + map -> { + // transform the map of name: JsonArrayBuilder to + // name: JsonArray + // using the downstream collector for reducing the JsonArray + JsonObjectBuilder objectBuilder = Json.createObjectBuilder(); + map.forEach((k, v) -> { + JsonArray array = downstream.finisher().apply(v); + objectBuilder.add(k, array); + }); + return objectBuilder.build(); + }; + BinaryOperator<Map<String, T>> combiner = + (map1, map2) -> { + map1.putAll(map2); + return map1; + }; + return Collector.of(HashMap::new, accumulator, combiner, finisher, + Collector.Characteristics.UNORDERED); + } + + /** + * Constructs a {@code java.util.stream.Collector} that implements a "group by" operation on the + * input {@code JsonValue} elements. A classifier function maps the input {@code JsonValue}s to keys, and + * the {@code JsonValue}s are partitioned into groups according to the value of the key. + * The {@code JsonValue}s in each group are added to a {@code JsonArray}. The key and the + * {@code JsonArray} in each group becomes the name/value pair of the resultant {@code JsonObject}. + * + * @param classifier a function mapping the input {@code JsonValue}s to a String, producing keys + * @return the constructed {@code Collector} + */ + public static Collector<JsonValue, Map<String, JsonArrayBuilder>, JsonObject> + groupingBy(Function<JsonValue, String> classifier) { + return groupingBy(classifier, toJsonArray()); + } +} +
diff --git a/api/src/main/java/jakarta/json/stream/JsonGenerationException.java b/api/src/main/java/jakarta/json/stream/JsonGenerationException.java new file mode 100644 index 0000000..168d673 --- /dev/null +++ b/api/src/main/java/jakarta/json/stream/JsonGenerationException.java
@@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json.stream; + +import jakarta.json.JsonException; + +/** + * {@code JsonGenerationException} indicates an incorrect JSON is + * being generated. + */ +public class JsonGenerationException extends JsonException { + + /** + * Constructs a new runtime exception with the specified detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public JsonGenerationException(String message) { + super(message); + } + + /** + * Constructs a new runtime exception with the specified detail message and + * cause. <p>Note that the detail message associated with + * {@code cause} is <i>not</i> automatically incorporated in + * this runtime exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A <code>null</code> value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + */ + public JsonGenerationException(String message, Throwable cause) { + super(message, cause); + } + +} +
diff --git a/api/src/main/java/jakarta/json/stream/JsonGenerator.java b/api/src/main/java/jakarta/json/stream/JsonGenerator.java new file mode 100644 index 0000000..7ca3d3f --- /dev/null +++ b/api/src/main/java/jakarta/json/stream/JsonGenerator.java
@@ -0,0 +1,539 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json.stream; + +import jakarta.json.JsonValue; +import java.io.Closeable; +import java.io.Flushable; +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * Writes JSON data to an output source in a streaming way. The class + * {@link jakarta.json.Json} contains methods to create generators for character + * or output streams ({@link java.io.Writer} and {@link java.io.OutputStream}). + * + * <p> + * The following example shows how to create a JSON generator: + * <pre> + * <code> + * JsonGenerator generator = Json.createGenerator(...); + * </code> + * </pre> + * + * <p> + * The class {@link JsonGeneratorFactory} also contains methods to create + * {@code JsonGenerator} instances. {@link JsonGeneratorFactory} should be used + * when creating multiple generator instances, as in the following example: + * <pre> + * <code> + * JsonGeneratorFactory factory = Json.createGeneratorFactory(); + * JsonGenerator generator1 = factory.createGenerator(...); + * JsonGenerator generator2 = factory.createGenerator(...); + * </code> + * </pre> + * + * <p> + * JSON objects can be created using {@code JsonGenerator} by calling the + * {@link #writeStartObject()} method and then adding name/value pairs with the + * {@code write} method. + * <p> + * The following example shows how to generate an empty JSON object: + * <pre> + * <code> + * JsonGenerator generator = ...; + * generator.writeStartObject().writeEnd().close(); + * </code> + * </pre> + * + * JSON arrays can be created using {@code JsonGenerator} by calling the + * {@link #writeStartArray()} method and then adding values with the + * {@code write} method. + * + * <p> + * The following example shows how to generate an empty JSON array: + * <pre> + * <code> + * JsonGenerator generator = ...; + * generator.writeStartArray().writeEnd().close(); + * </code> + * </pre> + * + * <p> + * Other JSON values (that are not JSON objects or arrays) can be created + * by calling the appropiate {@code write} methods. + * <p> + * The following example shows how to generate a JSON string: + * <pre><code> + * JsonGenerator generator = ...; + * generator.write("message").close(); + * </code></pre> + * + * {@code JsonGenerator} methods can be chained as in the following example: + * <pre> + * <code> + * generator + * .writeStartObject() + * .write("firstName", "John") + * .write("lastName", "Smith") + * .write("age", 25) + * .writeStartObject("address") + * .write("streetAddress", "21 2nd Street") + * .write("city", "New York") + * .write("state", "NY") + * .write("postalCode", "10021") + * .writeEnd() + * .writeStartArray("phoneNumber") + * .writeStartObject() + * .write("type", "home") + * .write("number", "212 555-1234") + * .writeEnd() + * .writeStartObject() + * .write("type", "fax") + * .write("number", "646 555-4567") + * .writeEnd() + * .writeEnd() + * .writeEnd(); + * generator.close(); + * </code> + * </pre> + * + * The example code above generates the following JSON (or equivalent): + * <pre> + * <code> + * { + * "firstName": "John", "lastName": "Smith", "age": 25, + * "address" : { + * "streetAddress": "21 2nd Street", + * "city": "New York", + * "state": "NY", + * "postalCode": "10021" + * }, + * "phoneNumber": [ + * {"type": "home", "number": "212 555-1234"}, + * {"type": "fax", "number": "646 555-4567"} + * ] + * } + * </code> + * </pre> + * + * The generated JSON text must strictly conform to the grammar defined in + * <a href="http://www.ietf.org/rfc/rfc7159.txt">RFC 7159</a>. + * + * @see jakarta.json.Json + * @see JsonGeneratorFactory + */ +public interface JsonGenerator extends Flushable, /*Auto*/Closeable { + /** + * Configuration property to generate JSON prettily. All providers + * must support this property. The value of the property could be + * be anything. + */ + String PRETTY_PRINTING = "jakarta.json.stream.JsonGenerator.prettyPrinting" ; + + /** + * Writes the JSON start object character. It starts a new child object + * context within which JSON name/value pairs can be written to the object. + * This method is valid only in an array context, field context or in no context (when a + * context is not yet started). This method can only be called once in + * no context. + * + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is called within an + * object context or if it is called more than once in no context. + */ + JsonGenerator writeStartObject(); + + /** + * Writes the JSON name/start object character pair in the current + * object context. It starts a new child object context within which JSON + * name/value pairs can be written to the object. + * + * @param name a name within the JSON name/object pair to be written + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context + */ + JsonGenerator writeStartObject(String name); + + /** + * Writes the JSON name with a colon. It starts a field context, in which valid + * options are writing a value, starting an object or an array. + * + * Writing value closes field context, if object or array is started after field name, + * field context will be closed after object/array close. + * + * @param name name of json field + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context + * + * @since 1.1 + */ + JsonGenerator writeKey(String name); + + /** + * Writes the JSON start array character. It starts a new child array + * context within which JSON values can be written to the array. This + * method is valid only in an array context, field context or in no context (when a + * context is not yet started). This method can only be called once in + * no context. + * + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is called within an + * object context or if called more than once in no context + */ + JsonGenerator writeStartArray(); + + /** + * Writes the JSON name/start array character pair with in the current + * object context. It starts a new child array context within which JSON + * values can be written to the array. + * + * @param name a name within the JSON name/array pair to be written + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within + * an object context + */ + JsonGenerator writeStartArray(String name); + + /** + * Writes a JSON name/value pair in the current object context. + * + * @param name a name in the JSON name/value pair to be written in + * current JSON object + * @param value a value in the JSON name/value pair to be written in + * current JSON object + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context + */ + JsonGenerator write(String name, JsonValue value); + + /** + * Writes a JSON name/string value pair in the current object context. + * The specified value is written as JSON string value. + * + * @param name a name in the JSON name/string pair to be written in + * current JSON object + * @param value a value in the JSON name/string pair to be written in + * current JSON object + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context + */ + JsonGenerator write(String name, String value); + + /** + * Writes a JSON name/number value pair in the current object context. + * The specified value is written as a JSON number value. The string + * {@code new BigDecimal(value).toString()} + * is used as the text value for writing. + * + * @param name a name in the JSON name/number pair to be written in + * current JSON object + * @param value a value in the JSON name/number pair to be written in + * current JSON object + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context. + */ + JsonGenerator write(String name, BigInteger value); + + /** + * Writes a JSON name/number value pair in the current object context. + * The specified value is written as a JSON number value. The specified + * value's {@code toString()} is used as the text value for writing. + * + * @param name a name in the JSON name/number pair to be written in + * current JSON object + * @param value a value in the JSON name/number pair to be written in + * current JSON object + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context. + */ + JsonGenerator write(String name, BigDecimal value); + + /** + * Writes a JSON name/number value pair in the current object context. + * The specified value is written as a JSON number value. The string + * {@code new BigDecimal(value).toString()} is used as the text value + * for writing. + * + * @param name a name in the JSON name/number pair to be written in + * current JSON object + * @param value a value in the JSON name/number pair to be written in + * current JSON object + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context. + */ + JsonGenerator write(String name, int value); + + /** + * Writes a JSON name/number value pair in the current object context. + * The specified value is written as a JSON number value. The string + * {@code new BigDecimal(value).toString()} is used as the text + * value for writing. + * + * @param name a name in the JSON name/number pair to be written in + * current JSON object + * @param value a value in the JSON name/number pair to be written in + * current JSON object + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context. + */ + JsonGenerator write(String name, long value); + + /** + * Writes a JSON name/number value pair in the current object context. + * The specified value is written as a JSON number value. The string + * {@code BigDecimal.valueOf(double).toString()} + * is used as the text value for writing. + * + * @param name a name in the JSON name/number pair to be written in + * current JSON object + * @param value a value in the JSON name/number pair to be written in + * current JSON object + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws NumberFormatException if the value is Not-a-Number (NaN) or infinity. + * @throws JsonGenerationException if this method is not called within an + * object context + */ + JsonGenerator write(String name, double value); + + /** + * Writes a JSON name/boolean value pair in the current object context. + * If value is true, it writes the JSON {@code true} value, otherwise + * it writes the JSON {@code false} value. + * + * @param name a name in the JSON name/boolean pair to be written in + * current JSON object + * @param value a value in the JSON name/boolean pair to be written in + * current JSON object + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context. + */ + JsonGenerator write(String name, boolean value); + + + /** + * Writes a JSON name/null value pair in an current object context. + * + * @param name a name in the JSON name/null pair to be written in + * current JSON object + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * object context + */ + JsonGenerator writeNull(String name); + + /** + * Writes the end of the current context. If the current context is + * an array context, this method writes the end-of-array character (']'). + * If the current context is an object context, this method writes the + * end-of-object character ('}'). After writing the end of the current + * context, the parent context becomes the new current context. + * If parent context is field context, it is closed. + * + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is called in no context. + */ + JsonGenerator writeEnd(); + + /** + * Writes the specified value as a JSON value within + * the current array, field or root context. + * + * @param value a value to be written in current JSON array + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * array or root context. + */ + JsonGenerator write(JsonValue value); + + /** + * Writes the specified value as a JSON string value within + * the current array, field or root context. + * + * @param value a value to be written in current JSON array + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * array or root context. + */ + JsonGenerator write(String value); + + /** + * Writes the specified value as a JSON number value within + * the current array, field or root context. The specified value's {@code toString()} + * is used as the the text value for writing. + * + * @param value a value to be written in current JSON array + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * array or root context. + * + * @see jakarta.json.JsonNumber + */ + JsonGenerator write(BigDecimal value); + + /** + * Writes the specified value as a JSON number value within + * the current array, field or root context. The string {@code new BigDecimal(value).toString()} + * is used as the text value for writing. + * + * @param value a value to be written in current JSON array + * @return this generator. + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * array or root context. + * + * @see jakarta.json.JsonNumber + */ + JsonGenerator write(BigInteger value); + + /** + * Writes the specified value as a JSON number value within + * the current array, field or root context. The string {@code new BigDecimal(value).toString()} + * is used as the text value for writing. + * + * @param value a value to be written in current JSON array + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * array or root context. + */ + JsonGenerator write(int value); + + /** + * Writes the specified value as a JSON number value within + * the current array, field or root context. The string {@code new BigDecimal(value).toString()} + * is used as the text value for writing. + * + * @param value a value to be written in current JSON array + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * array or root context. + */ + JsonGenerator write(long value); + + /** + * Writes the specified value as a JSON number value within the current + * array, field or root context. The string {@code BigDecimal.valueOf(value).toString()} + * is used as the text value for writing. + * + * @param value a value to be written in current JSON array + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * array or root context. + * @throws NumberFormatException if the value is Not-a-Number (NaN) or infinity. + */ + JsonGenerator write(double value); + + /** + * Writes a JSON true or false value within the current array, field or root context. + * If value is true, this method writes the JSON {@code true} value, + * otherwise it writes the JSON {@code false} value. + * + * @param value a {@code boolean} value + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * array or root context. + */ + JsonGenerator write(boolean value); + + /** + * Writes a JSON null value within the current array, field or root context. + * + * @return this generator + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if this method is not called within an + * array or root context. + */ + JsonGenerator writeNull(); + + /** + * Closes this generator and frees any resources associated with it. + * This method closes the underlying output source. + * + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonGenerationException if an incomplete JSON is generated + */ + @Override + void close(); + + /** + * Flushes the underlying output source. If the generator has saved + * any characters in a buffer, writes them immediately to the underlying + * output source before flushing it. + * + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + */ + @Override + void flush(); + +}
diff --git a/api/src/main/java/jakarta/json/stream/JsonGeneratorFactory.java b/api/src/main/java/jakarta/json/stream/JsonGeneratorFactory.java new file mode 100644 index 0000000..2483e7a --- /dev/null +++ b/api/src/main/java/jakarta/json/stream/JsonGeneratorFactory.java
@@ -0,0 +1,89 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json.stream; + +import java.io.OutputStream; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.Map; + +/** + * Factory to create {@link JsonGenerator} instances. If a factory + * instance is configured with some configuration, the configuration applies + * to all generator instances created using that factory instance. + * + * <p> + * The class {@link jakarta.json.Json Json} also provides methods to create + * {@link JsonGenerator} instances, but using {@code JsonGeneratorFactory} is + * preferred when creating multiple generator instances as shown in the + * following example: + * + * <pre> + * <code> + * JsonGeneratorFactory factory = Json.createGeneratorFactory(); + * JsonGenerator generator1 = factory.createGenerator(...); + * JsonGenerator generator2 = factory.createGenerator(...); + * </code> + * </pre> + * + * <p> All the methods in this class are safe for use by multiple concurrent + * threads. + */ +public interface JsonGeneratorFactory { + + /** + * Creates a JSON generator to write JSON text to a character stream. + * The generator is configured with the factory configuration. + * + * @param writer i/o writer to which JSON is written + * @return the created JSON generator + */ + JsonGenerator createGenerator(Writer writer); + + /** + * Creates a JSON generator to write JSON text to a byte stream. Characters + * written to the stream are encoded into bytes using UTF-8 encoding. + * The generator is configured with the factory's configuration. + * + * @param out i/o stream to which JSON is written + * @return the created JSON generator + */ + JsonGenerator createGenerator(OutputStream out); + + /** + * Creates a JSON generator to write JSON text to a byte stream. Characters + * written to the stream are encoded into bytes using the specified charset. + * The generator is configured with the factory's configuration. + * + * @param out i/o stream to which JSON is written + * @param charset a charset + * @return the created JSON generator + */ + JsonGenerator createGenerator(OutputStream out, Charset charset); + + /** + * Returns a read-only map of supported provider specific configuration + * properties that are used to configure the JSON generators. + * If there are any specified configuration properties that are not + * supported by the provider, they won't be part of the returned map. + * + * @return a map of supported provider specific properties that are used + * to configure the created generators. The map may be empty but not null + */ + Map<String, ?> getConfigInUse(); + +}
diff --git a/api/src/main/java/jakarta/json/stream/JsonLocation.java b/api/src/main/java/jakarta/json/stream/JsonLocation.java new file mode 100644 index 0000000..3bf5567 --- /dev/null +++ b/api/src/main/java/jakarta/json/stream/JsonLocation.java
@@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json.stream; + +/** + * Provides the location information of a JSON event in an input source. The + * {@code JsonLocation} information can be used to identify incorrect JSON + * or can be used by higher frameworks to know about the processing location. + * + * <p>All the information provided by a {@code JsonLocation} is optional. For + * example, a provider may only report line numbers. Also, there may not be any + * location information for an input source. For example, if a + * {@code JsonParser} is created using + * {@link jakarta.json.JsonArray JsonArray} input source, all the methods in + * this class return -1. + * @see JsonParser + * @see JsonParsingException + */ +public interface JsonLocation { + + /** + * Return the line number (starts with 1 for the first line) for the current JSON event in the input source. + * + * @return the line number (starts with 1 for the first line) or -1 if none is available + */ + long getLineNumber(); + + /** + * Return the column number (starts with 1 for the first column) for the current JSON event in the input source. + * + * @return the column number (starts with 1 for the first column) or -1 if none is available + */ + long getColumnNumber(); + + /** + * Return the stream offset into the input source this location + * is pointing to. If the input source is a file or a byte stream then + * this is the byte offset into that stream, but if the input source is + * a character media then the offset is the character offset. + * Returns -1 if there is no offset available. + * + * @return the offset of input source stream, or -1 if there is + * no offset available + */ + long getStreamOffset(); + +}
diff --git a/api/src/main/java/jakarta/json/stream/JsonParser.java b/api/src/main/java/jakarta/json/stream/JsonParser.java new file mode 100644 index 0000000..e455a6e --- /dev/null +++ b/api/src/main/java/jakarta/json/stream/JsonParser.java
@@ -0,0 +1,487 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json.stream; + + +import java.io.Closeable; +import java.math.BigDecimal; +import java.util.stream.Stream; +import java.util.Map; + +import jakarta.json.JsonValue; +import jakarta.json.JsonObject; +import jakarta.json.JsonArray; + +/** + * Provides forward, read-only access to JSON data in a streaming way. This + * is the most efficient way for reading JSON data. + * This is the only way to parse and process JSON data that are too big to be loaded in memory. + * <p>The class + * {@link jakarta.json.Json} contains methods to create parsers from input + * sources ({@link java.io.InputStream} and {@link java.io.Reader}). + * + * <p> + * The following example demonstrates how to create a parser from a string + * that contains an empty JSON array: + * <pre> + * <code> + * JsonParser parser = Json.createParser(new StringReader("[]")); + * </code> + * </pre> + * + * <p> + * The class {@link JsonParserFactory} also contains methods to create + * {@code JsonParser} instances. {@link JsonParserFactory} is preferred + * when creating multiple parser instances. A sample usage is shown + * in the following example: + * <pre> + * <code> + * JsonParserFactory factory = Json.createParserFactory(); + * JsonParser parser1 = factory.createParser(...); + * JsonParser parser2 = factory.createParser(...); + * </code> + * </pre> + * + * <p> + * {@code JsonParser} parses JSON using the pull parsing programming model. + * In this model the client code controls the thread and calls the method + * {@code next()} to advance the parser to the next state after + * processing each element. The parser can generate the following events: + * {@code START_OBJECT}, {@code END_OBJECT}, {@code START_ARRAY}, + * {@code END_ARRAY}, {@code KEY_NAME}, {@code VALUE_STRING}, + * {@code VALUE_NUMBER}, {@code VALUE_TRUE}, {@code VALUE_FALSE}, + * and {@code VALUE_NULL}. + * + * <p> + * <b>For example</b>, for an empty JSON object ({ }), the parser generates the event + * {@code START_OBJECT} with the first call to the method {@code next()} and the + * event {@code END_OBJECT} with the second call to the method {@code next()}. + * The following code demonstrates how to access these events: + * + * <pre> + * <code> + * Event event = parser.next(); // START_OBJECT + * event = parser.next(); // END_OBJECT + * </code> + * </pre> + * + * <p> + * <b>For example</b>, for the following JSON: + * <pre> + * { + * "firstName": "John", "lastName": "Smith", "age": 25, + * "phoneNumber": [ + * { "type": "home", "number": "212 555-1234" }, + * { "type": "fax", "number": "646 555-4567" } + * ] + * } + * </pre> + * + * <p>calls to the method {@code next()} result in parse events at the specified + * locations below (marked in bold): + * + * <pre> + * {<B>START_OBJECT</B> + * "firstName"<B>KEY_NAME</B>: "John"<B>VALUE_STRING</B>, "lastName"<B>KEY_NAME</B>: "Smith"<B>VALUE_STRING</B>, "age"<B>KEY_NAME</B>: 25<B>VALUE_NUMBER</B>, + * "phoneNumber"<B>KEY_NAME</B> : [<B>START_ARRAY</B> + * {<B>START_OBJECT</B> "type"<B>KEY_NAME</B>: "home"<B>VALUE_STRING</B>, "number"<B>KEY_NAME</B>: "212 555-1234"<B>VALUE_STRING</B> }<B>END_OBJECT</B>, + * {<B>START_OBJECT</B> "type"<B>KEY_NAME</B>: "fax"<B>VALUE_STRING</B>, "number"<B>KEY_NAME</B>: "646 555-4567"<B>VALUE_STRING</B> }<B>END_OBJECT</B> + * ]<B>END_ARRAY</B> + * }<B>END_OBJECT</B> + * </pre> + * + * The methods {@link #next()} and {@link #hasNext()} enable iteration over + * parser events to process JSON data. {@code JsonParser} provides get methods + * to obtain the value at the current state of the parser. For example, the + * following code shows how to obtain the value "John" from the JSON above: + * + * <pre> + * <code> + * Event event = parser.next(); // START_OBJECT + * event = parser.next(); // KEY_NAME + * event = parser.next(); // VALUE_STRING + * parser.getString(); // "John" + * </code> + * </pre> + * + * Starting in version 1.1, it is possible to build a partial JSON object + * model from the stream, at the current parser position. + * The methods {@link #getArray} and {@link #getObject} can be used to read in + * a {@code JsonArray} or {@code JsonObject}. For example, the following code + * shows how to obtain the phoneNumber in a JsonArray, from the JSON above: + * + * <pre><code> + * while (parser.hasNext() { + * Event event = parser.next(); + * if (event == JsonParser.Event.KEY_NAME ) { + * String key = getString(); + * event = parser.next(); + * if (key.equals("phoneNumber") { + * JsonArray phones = parser.getArray(); + * } + * } + * } + * </code></pre> + * + * The methods {@link #getArrayStream} and {@link #getObjectStream} can be used + * to get a stream of the elements of a {@code JsonArray} or {@code JsonObject}. + * For example, the following code shows another way to obtain John's phoneNumber + * in a {@code JsonArray} : + * + * <pre>{@code + * Event event = parser.next(); // START_OBJECT + * JsonArray phones = (JsonArray) + * parser.getObjectStream().filter(e->e.getKey().equals("phoneNumber")) + * .map(e->e.getValue()) + * .findFirst() + * .get(); + * }</pre> + * + * The methods {@link #skipArray} and {@link #skipObject} can be used to + * skip tokens and position the parser to {@code END_ARRAY} or + * {@code END_OBJECT}. + * <p> + * {@code JsonParser} can be used to parse sequence of JSON values that are not + * enclosed in a JSON array, e.g. { } { }. The following code demonstrates how + * to parse such sequence. + * <pre><code> + * JsonParser parser = Json.createParser(...); + * while (parser.hasNext) { + * parser.next(); // advance parser state + * JsonValue value = parser.getValue(); + * } + * </code></pre> + * + * @see jakarta.json.Json + * @see JsonParserFactory + */ +public interface JsonParser extends /*Auto*/Closeable { + + /** + * An event from {@code JsonParser}. + */ + enum Event { + /** + * Start of a JSON array. The position of the parser is after '['. + */ + START_ARRAY, + /** + * Start of a JSON object. The position of the parser is after '{'. + */ + START_OBJECT, + /** + * Name in a name/value pair of a JSON object. The position of the parser + * is after the key name. The method {@link #getString} returns the key + * name. + */ + KEY_NAME, + /** + * String value in a JSON array or object. The position of the parser is + * after the string value. The method {@link #getString} + * returns the string value. + */ + VALUE_STRING, + /** + * Number value in a JSON array or object. The position of the parser is + * after the number value. {@code JsonParser} provides the following + * methods to access the number value: {@link #getInt}, + * {@link #getLong}, and {@link #getBigDecimal}. + */ + VALUE_NUMBER, + /** + * {@code true} value in a JSON array or object. The position of the + * parser is after the {@code true} value. + */ + VALUE_TRUE, + /** + * {@code false} value in a JSON array or object. The position of the + * parser is after the {@code false} value. + */ + VALUE_FALSE, + /** + * {@code null} value in a JSON array or object. The position of the + * parser is after the {@code null} value. + */ + VALUE_NULL, + /** + * End of a JSON object. The position of the parser is after '}'. + */ + END_OBJECT, + /** + * End of a JSON array. The position of the parser is after ']'. + */ + END_ARRAY + } + + /** + * Returns {@code true} if there are more parsing states. This method returns + * {@code false} if the parser reaches the end of the JSON text. + * + * @return {@code true} if there are more parsing states. + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonParsingException if the parser encounters invalid JSON + * when advancing to next state. + */ + boolean hasNext(); + + /** + * Returns the event for the next parsing state. + * + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + * @throws JsonParsingException if the parser encounters invalid JSON + * when advancing to next state. + * @throws java.util.NoSuchElementException if there are no more parsing + * states. + * @return the event for the next parsing state + */ + Event next(); + + /** + * Returns a {@code String} for the name in a name/value pair, + * for a string value or a number value. This method should only be called + * when the parser state is {@link Event#KEY_NAME}, {@link Event#VALUE_STRING}, + * or {@link Event#VALUE_NUMBER}. + * + * @return a name when the parser state is {@link Event#KEY_NAME} + * a string value when the parser state is {@link Event#VALUE_STRING} + * a number value when the parser state is {@link Event#VALUE_NUMBER} + * @throws IllegalStateException when the parser state is not + * {@code KEY_NAME}, {@code VALUE_STRING}, or {@code VALUE_NUMBER} + */ + String getString(); + + /** + * Returns true if the JSON number at the current parser state is a + * integral number. A {@link BigDecimal} may be used to store the value + * internally and this method semantics are defined using its + * {@code scale()}. If the scale is zero, then it is considered integral + * type. This integral type information can be used to invoke an + * appropriate accessor method to obtain a numeric value as in the + * following example: + * + * <pre> + * <code> + * JsonParser parser = ... + * if (parser.isIntegralNumber()) { + * parser.getInt(); // or other methods to get integral value + * } else { + * parser.getBigDecimal(); + * } + * </code> + * </pre> + * + * @return true if this number is a integral number, otherwise false + * @throws IllegalStateException when the parser state is not + * {@code VALUE_NUMBER} + */ + boolean isIntegralNumber(); + + /** + * Returns a JSON number as an integer. The returned value is equal + * to {@code new BigDecimal(getString()).intValue()}. Note that + * this conversion can lose information about the overall magnitude + * and precision of the number value as well as return a result with + * the opposite sign. This method should only be called when the parser + * state is {@link Event#VALUE_NUMBER}. + * + * @return an integer for a JSON number + * @throws IllegalStateException when the parser state is not + * {@code VALUE_NUMBER} + * @see java.math.BigDecimal#intValue() + */ + int getInt(); + + /** + * Returns a JSON number as a long. The returned value is equal + * to {@code new BigDecimal(getString()).longValue()}. Note that this + * conversion can lose information about the overall magnitude and + * precision of the number value as well as return a result with + * the opposite sign. This method is only called when the parser state is + * {@link Event#VALUE_NUMBER}. + * + * @return a long for a JSON number + * @throws IllegalStateException when the parser state is not + * {@code VALUE_NUMBER} + * @see java.math.BigDecimal#longValue() + */ + long getLong(); + + /** + * Returns a JSON number as a {@code BigDecimal}. The {@code BigDecimal} + * is created using {@code new BigDecimal(getString())}. This + * method should only called when the parser state is + * {@link Event#VALUE_NUMBER}. + * + * @return a {@code BigDecimal} for a JSON number + * @throws IllegalStateException when the parser state is not + * {@code VALUE_NUMBER} + */ + BigDecimal getBigDecimal(); + + /** + * Return the location that corresponds to the parser's current state in + * the JSON input source. The location information is only valid in the + * current parser state (or until the parser is advanced to a next state). + * + * @return a non-null location corresponding to the current parser state + * in JSON input source + */ + JsonLocation getLocation(); + + /** + * Returns a {@code JsonObject} and advances the parser to the + * corresponding {@code END_OBJECT}. + * + * @return the {@code JsonObject} at the current parser position + * + * @throws IllegalStateException when the parser state is not + * {@code START_OBJECT} + * + * @since 1.1 + */ + default public JsonObject getObject() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a {@code JsonValue} at the current parser position. + * If the parser state is {@code START_ARRAY}, the behavior is + * the same as {@link #getArray}. If the parser state is + * {@code START_OBJECT}, the behavior is the same as + * {@link #getObject}. For all other cases, if applicable, the JSON value is + * read and returned. + * + * @return the {@code JsonValue} at the current parser position. + * @throws IllegalStateException when the parser state is + * {@code END_OBJECT} or {@code END_ARRAY} + * + * @since 1.1 + */ + default public JsonValue getValue() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a {@code JsonArray} and advance the parser to the + * the corresponding {@code END_ARRAY}. + * + * @return the {@code JsonArray} at the current parser position + * + * @throws IllegalStateException when the parser state is not + * {@code START_ARRAY} + * + * @since 1.1 + */ + default public JsonArray getArray() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a stream of the {@code JsonArray} elements. + * The parser state must be {@code START_ARRAY}. + * The elements are read lazily, on an as-needed basis, as + * required by the stream operations. + * If the stream operations do not consume + * all of the array elements, {@link skipArray} can be used to + * skip the unprocessed array elements. + * + * @return a stream of elements of the {@code JsonArray} + * + * @throws IllegalStateException when the parser state is not + * {@code START_ARRAY} + * + * @since 1.1 + */ + default public Stream<JsonValue> getArrayStream() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a stream of the {@code JsonObject}'s + * name/value pairs. The parser state must be {@code START_OBJECT}. + * The name/value pairs are read lazily, on an as-needed basis, as + * required by the stream operations. + * If the stream operations do not consume + * all of the object's name/value pairs, {@link skipObject} can be + * used to skip the unprocessed elements. + * + * @return a stream of name/value pairs of the {@code JsonObject} + * + * @throws IllegalStateException when the parser state is not + * {@code START_OBJECT} + * + * @since 1.1 + */ + default public Stream<Map.Entry<String,JsonValue>> getObjectStream() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a stream of {@code JsonValue} from a sequence of + * JSON values. The values are read lazily, on an as-needed basis, + * as needed by the stream operations. + * + * @return a Stream of {@code JsonValue} + * + * @throws IllegalStateException if the parser is in an array or object. + * + * @since 1.1 + */ + default public Stream<JsonValue> getValueStream() { + throw new UnsupportedOperationException(); + } + + /** + * Advance the parser to {@code END_ARRAY}. + * If the parser is in array context, i.e. it has previously + * encountered a {@code START_ARRAY} without encountering the + * corresponding {@code END_ARRAY}, the parser is advanced to + * the corresponding {@code END_ARRAY}. + * If the parser is not in any array context, nothing happens. + * + * @since 1.1 + */ + default public void skipArray() { + throw new UnsupportedOperationException(); + } + + /** + * Advance the parser to {@code END_OBJECT}. + * If the parser is in object context, i.e. it has previously + * encountered a {@code START_OBJECT} without encountering the + * corresponding {@code END_OBJECT}, the parser is advanced to + * the corresponding {@code END_OBJECT}. + * If the parser is not in any object context, nothing happens. + * + * @since 1.1 + */ + default public void skipObject() { + throw new UnsupportedOperationException(); + } + + /** + * Closes this parser and frees any resources associated with the + * parser. This method closes the underlying input source. + * + * @throws jakarta.json.JsonException if an i/o error occurs (IOException + * would be cause of JsonException) + */ + @Override + void close(); +}
diff --git a/api/src/main/java/jakarta/json/stream/JsonParserFactory.java b/api/src/main/java/jakarta/json/stream/JsonParserFactory.java new file mode 100644 index 0000000..3434411 --- /dev/null +++ b/api/src/main/java/jakarta/json/stream/JsonParserFactory.java
@@ -0,0 +1,108 @@ +/* + * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json.stream; + +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import java.io.InputStream; +import java.io.Reader; +import java.nio.charset.Charset; +import java.util.Map; + +/** + * Factory for creating {@link JsonParser} instances. If a factory + * instance is configured with a configuration, the configuration applies + * to all parser instances created using that factory instance. + * + * <p> + * The class {@link jakarta.json.Json Json} also provides methods to create + * {@link JsonParser} instances, but using {@code JsonParserFactory} is + * preferred when creating multiple parser instances as shown in the following + * example: + * + * <pre> + * <code> + * JsonParserFactory factory = Json.createParserFactory(); + * JsonParser parser1 = factory.createParser(...); + * JsonParser parser2 = factory.createParser(...); + * </code> + * </pre> + * + * <p> All the methods in this class are safe for use by multiple concurrent + * threads. + */ +public interface JsonParserFactory { + + /** + * Creates a JSON parser from a character stream. + * + * @param reader a i/o reader from which JSON is to be read + * @return the created JSON parser + */ + JsonParser createParser(Reader reader); + + /** + * Creates a JSON parser from the specified byte stream. + * The character encoding of the stream is determined + * as specified in <a href="http://tools.ietf.org/rfc/rfc7159.txt">RFC 7159</a>. + * + * @param in i/o stream from which JSON is to be read + * @return the created JSON parser + * @throws jakarta.json.JsonException if encoding cannot be determined + * or i/o error (IOException would be cause of JsonException) + */ + JsonParser createParser(InputStream in); + + /** + * Creates a JSON parser from the specified byte stream. + * The bytes of the stream are decoded to characters using the + * specified charset. + * + * @param in i/o stream from which JSON is to be read + * @param charset a charset + * @return the created JSON parser + */ + JsonParser createParser(InputStream in, Charset charset); + + /** + * Creates a JSON parser from the specified JSON object. + * + * @param obj a JSON object + * @return the created JSON parser + */ + JsonParser createParser(JsonObject obj); + + /** + * Creates a JSON parser from the specified JSON array. + * + * @param array a JSON array + * @return the created JSON parser + */ + JsonParser createParser(JsonArray array); + + /** + * Returns a read-only map of supported provider specific configuration + * properties that are used to configure the JSON parsers. + * If there are any specified configuration properties that are not + * supported by the provider, they won't be part of the returned map. + * + * @return a map of supported provider specific properties that are used + * to configure the created parsers. The map may be empty but not null + */ + Map<String, ?> getConfigInUse(); + +}
diff --git a/api/src/main/java/jakarta/json/stream/JsonParsingException.java b/api/src/main/java/jakarta/json/stream/JsonParsingException.java new file mode 100644 index 0000000..ffca1e0 --- /dev/null +++ b/api/src/main/java/jakarta/json/stream/JsonParsingException.java
@@ -0,0 +1,72 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.json.stream; + +import jakarta.json.JsonException; + +/** + * {@code JsonParsingException} is used when an incorrect JSON is + * being parsed. + */ +public class JsonParsingException extends JsonException { + + private final JsonLocation location; + + /** + * Constructs a new runtime exception with the specified detail message. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + * @param location the location of the incorrect JSON + */ + public JsonParsingException(String message, JsonLocation location) { + super(message); + this.location = location; + } + + /** + * Constructs a new runtime exception with the specified detail message and + * cause. <p>Note that the detail message associated with + * {@code cause} is <i>not</i> automatically incorporated in + * this runtime exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A <code>null</code> value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @param location the location of the incorrect JSON + */ + public JsonParsingException(String message, Throwable cause, JsonLocation location) { + super(message, cause); + this.location = location; + } + + /** + * Return the location of the incorrect JSON. + * + * @return the non-null location of the incorrect JSON + */ + public JsonLocation getLocation() { + return location; + } + +} +
diff --git a/api/src/main/java/jakarta/json/stream/package-info.java b/api/src/main/java/jakarta/json/stream/package-info.java new file mode 100644 index 0000000..bd57cdb --- /dev/null +++ b/api/src/main/java/jakarta/json/stream/package-info.java
@@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/** + * Provides a streaming API to parse and generate + * <a href="http://json.org/">JSON</a>. + * + * <p> + * The streaming API consists of the interfaces + * {@link jakarta.json.stream.JsonParser} and + * {@link jakarta.json.stream.JsonGenerator}. The interface {@code JsonParser} + * contains methods to parse JSON in a streaming way. The interface + * {@code JsonGenerator} contains methods to write JSON to an output source + * in a streaming way. + * + * <p> + * {@code JsonParser} provides forward, read-only access to JSON data using the + * pull parsing programming model. In this model the application code controls + * the thread and calls methods in the parser interface to move the parser + * forward or to obtain JSON data from the current state of the parser. + * + * <p> + * {@code JsonGenerator} provides methods to write JSON to an output source. + * The generator writes name/value pairs in JSON objects and values in JSON + * arrays. + * + * <p> + * The streaming API is a low-level API designed to process large amounts of + * JSON data efficiently. Other JSON frameworks (such as JSON binding) can be + * implemented using this API. + * + * @since JSON Processing 1.0 + */ +package jakarta.json.stream;
diff --git a/api/src/main/java/module-info.java b/api/src/main/java/module-info.java new file mode 100644 index 0000000..46a321c --- /dev/null +++ b/api/src/main/java/module-info.java
@@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/** + * Jakarta JSON Processing API. + */ +module jakarta.json { + exports jakarta.json; + exports jakarta.json.spi; + exports jakarta.json.stream; + uses jakarta.json.spi.JsonProvider; +}
diff --git a/api/src/main/javadoc/doc-files/speclicense.html b/api/src/main/javadoc/doc-files/speclicense.html new file mode 100644 index 0000000..ba29e5e --- /dev/null +++ b/api/src/main/javadoc/doc-files/speclicense.html
@@ -0,0 +1,72 @@ +<html> +<head> +<title>Eclipse Foundation Specification License - v1.0</title> +</head> +<body> +<h1>Eclipse Foundation Specification License - v1.0</h1> +<p>By using and/or copying this document, or the Eclipse Foundation + document from which this statement is linked, you (the licensee) agree + that you have read, understood, and will comply with the following + terms and conditions:</p> + +<p>Permission to copy, and distribute the contents of this document, or + the Eclipse Foundation document from which this statement is linked, in + any medium for any purpose and without fee or royalty is hereby + granted, provided that you include the following on ALL copies of the + document, or portions thereof, that you use:</p> + +<ul> + <li> link or URL to the original Eclipse Foundation document.</li> + <li>All existing copyright notices, or if one does not exist, a notice + (hypertext is preferred, but a textual representation is permitted) + of the form: "Copyright © [$date-of-document] + “Eclipse Foundation, Inc. <<url to this license>> + " + </li> +</ul> + +<p>Inclusion of the full text of this NOTICE must be provided. We + request that authorship attribution be provided in any software, + documents, or other items or products that you create pursuant to the + implementation of the contents of this document, or any portion + thereof.</p> + +<p>No right to create modifications or derivatives of Eclipse Foundation + documents is granted pursuant to this license, except anyone may + prepare and distribute derivative works and portions of this document + in software that implements the specification, in supporting materials + accompanying such software, and in documentation of such software, + PROVIDED that all such works include the notice below. HOWEVER, the + publication of derivative works of this document for use as a technical + specification is expressly prohibited.</p> + +<p>The notice is:</p> + +<p>"Copyright © 2018 Eclipse Foundation. This software or + document includes material copied from or derived from [title and URI + of the Eclipse Foundation specification document]."</p> + +<h2>Disclaimers</h2> + +<p>THIS DOCUMENT IS PROVIDED "AS IS," AND THE COPYRIGHT + HOLDERS AND THE ECLIPSE FOUNDATION MAKE NO REPRESENTATIONS OR + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, + NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE + SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS + WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR + OTHER RIGHTS.</p> + +<p>THE COPYRIGHT HOLDERS AND THE ECLIPSE FOUNDATION WILL NOT BE LIABLE + FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT + OF ANY USE OF THE DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE + CONTENTS THEREOF.</p> + +<p>The name and trademarks of the copyright holders or the Eclipse + Foundation may NOT be used in advertising or publicity pertaining to + this document or its contents without specific, written prior + permission. Title to copyright in this document will at all times + remain with copyright holders.</p> + +</body> +</html>
diff --git a/api/src/main/javadoc/overview.html b/api/src/main/javadoc/overview.html new file mode 100644 index 0000000..2b82208 --- /dev/null +++ b/api/src/main/javadoc/overview.html
@@ -0,0 +1,108 @@ +<html> +<!-- + + Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<body> +Jakarta JSON Processing provides portable APIs to parse, +generate, transform, and query <a href="http://json.org/">JSON</a> using the +streaming API or the object model API. + +<p>The Streaming API provides a way to parsing and generation of JSON in a +streaming fashion. It hands over parsing and generation control to the +programmer. The streaming API provides an event-based parser and allows an +application developer to ask for the next event rather than handling the event +in a callback. This gives a developer more procedural control over +the processing of the JSON. Application code can process or discard +the parser event, and ask for the next event(pull the event). The +streaming model is adequate for local processing where random access of other +parts of the data is not required. Similarly, the streaming API provides +a way to generate well-formed JSON to a stream by writing one event at a time. + +<p>The object model API creates a random access tree-like structure that +represents the JSON data in memory. The tree can then be navigated and +queried. This programming model is the most flexible and enables processing +that requires random access to the complete contents of the tree. However, +it is often not as efficient as the streaming model and requires more memory. +The object model generates JSON output by navigating the entire tree at once. + +<h1>The Streaming API</h1> +<p>The streaming API is similar to the StAX API for XML and consists of the +interfaces {@link jakarta.json.stream.JsonParser} and +{@link jakarta.json.stream.JsonGenerator}. {@code JsonParser} +contains methods to parse JSON data using the streaming model. +{@code JsonGenerator} contains methods to write JSON data to an ouptut source. + +<p>{@code JsonParser} provides forward, read-only access to +JSON data using the pull parsing programming model. In this model the +application code controls the thread and calls methods in the parser interface +to move the parser forward or to obtain JSON data from the current state of +the parser. Refer to +<a href="jakarta.json/jakarta/json/stream/JsonParser.html#JsonParserExample2">this example</a> +for more details. + +<p>{@code JsonGenerator} provides methods to write JSON to a stream. The +generator writes name/value pairs in JSON objects and values in JSON arrays. +Refer to +<a href="jakarta.json/jakarta/json/stream/JsonGenerator.html#JsonGeneratorExample3">this +example</a> for more details. + +<p>The streaming API is a low-level API designed to process large amounts of +JSON data efficiently. Other JSON frameworks (such as JSON binding) can be +implemented using this API.</p> + +<h1>The Object Model API</h1> +<p>The object model API is similar to the DOM API for XML. It is a high-level +API that provides immutable object models for JSON object and array structures. +These JSON structures are represented as object models using the Java types +{@link jakarta.json.JsonObject} and {@link jakarta.json.JsonArray}. +{@code JsonObject} provides a {@link java.util.Map} view to access the unordered +collection of zero or more name/value pairs from the model. Similarly, +{@code JsonArray} provides a {@link java.util.List} view to access the ordered +sequence of zero or more values from the model. + +<p>The object model API uses builder patterns to create these object models. +Application code can use the interface {@link jakarta.json.JsonObjectBuilder} +to create models that represent JSON objects. The resulting model is of type +{@code JsonObject}. Refer to +<a href="jakarta.json/jakarta/json/JsonObjectBuilder.html#JsonObjectBuilderExample1">this example</a> +for more details. Application code can use the interface +{@link jakarta.json.JsonArrayBuilder} to create models that represent JSON arrays. +The resulting model is of type {@code JsonArray}. Refer to +<a href="jakarta.json/jakarta/json/JsonArrayBuilder.html#JsonArrayBuilderExample1">this example</a> +for more details. + +<p>These object models can also be created from an input source (such as +{@link java.io.InputStream} or {@link java.io.Reader}) using the interface +{@link jakarta.json.JsonReader}. +<a href="jakarta.json/jakarta/json/JsonReader.html#JsonReaderExample1">This example</a> shows +how to read and create an empty {@code JsonArray} model using the interface +{@code JsonReader}. Similarly, these object models can be written to an output +source (such as {@link java.io.OutputStream} or {@link java.io.Writer}) using +the class {@link jakarta.json.JsonWriter}. +<a href="jakarta.json/jakarta/json/JsonWriter.html#JsonWriterExample1">This example</a> shows +how to write an empty {@code JsonObject} model using the interface +{@code JsonWriter}. + +<h1>JSON Pointer, JSON Patch, and JSON Merge Patch</h1> +Jakarta JSON Processing supports the latest standard on +<a href="http://tools.ietf.org/html/rfc6901">JSON Pointer</a>, +<a Href="http://tools.ietf.org/html/rfc6902">JSON Patch</a>, and +<a Href="http://tools.ietf.org/html/rfc7396">JSON Merge Patch</a>. + +</body> +</html>
diff --git a/bundles/pom.xml b/bundles/pom.xml new file mode 100644 index 0000000..f90a6fb --- /dev/null +++ b/bundles/pom.xml
@@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish</groupId> + <artifactId>json</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <groupId>org.glassfish</groupId> + <artifactId>json-bundles</artifactId> + <packaging>pom</packaging> + <name>Jakarta JSON Processing bundles</name> + <description>Jakarta JSON Processing bundles</description> + <url>https://github.com/eclipse-ee4j/jsonp</url> + + <modules> + <module>ri</module> + </modules> +</project>
diff --git a/bundles/ri/pom.xml b/bundles/ri/pom.xml new file mode 100755 index 0000000..cfc8cd0 --- /dev/null +++ b/bundles/ri/pom.xml
@@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.glassfish</groupId> + <artifactId>json-bundles</artifactId> + <version>2.0.1</version> + </parent> + + <artifactId>json-ri-bundle</artifactId> + <name>RI Distribution zip bundle</name> + <packaging>pom</packaging> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + <classifier>module</classifier> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jsonp-jaxrs</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <finalName>jakarta.json-ri-${impl_version}</finalName> + <descriptors> + <descriptor>src/main/assembly/archive.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project>
diff --git a/bundles/ri/src/main/assembly/archive.xml b/bundles/ri/src/main/assembly/archive.xml new file mode 100755 index 0000000..1c9e053 --- /dev/null +++ b/bundles/ri/src/main/assembly/archive.xml
@@ -0,0 +1,62 @@ +<!-- + + Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<assembly> + <id>dist</id> + <formats> + <format>zip</format> + </formats> + <files> + <file> + <source>src/main/resources/README.txt</source> + <outputDirectory></outputDirectory> + <filtered>true</filtered> + </file> + <file> + <source>src/main/resources/LICENSE.md</source> + <outputDirectory></outputDirectory> + </file> + </files> + <dependencySets> + <dependencySet> + <useProjectArtifact>false</useProjectArtifact> + <outputDirectory>mods</outputDirectory> + <includes> + <include>jakarta.json:jakarta.json-api:*</include> + <include>org.glassfish:jakarta.json:jar:module:*</include> + </includes> + </dependencySet> + <dependencySet> + <useProjectArtifact>false</useProjectArtifact> + <outputDirectory>standalone</outputDirectory> + <includes> + <include>org.glassfish:jakarta.json</include> + </includes> + <excludes> + <exclude>org.glassfish:jakarta.json:jar:module:*</exclude> + </excludes> + </dependencySet> + <dependencySet> + <useProjectArtifact>false</useProjectArtifact> + <outputDirectory>jaxrs</outputDirectory> + <includes> + <include>org.glassfish:jsonp-jaxrs*</include> + </includes> + </dependencySet> + </dependencySets> +</assembly>
diff --git a/bundles/ri/src/main/resources/LICENSE.md b/bundles/ri/src/main/resources/LICENSE.md new file mode 100644 index 0000000..5de3d1b --- /dev/null +++ b/bundles/ri/src/main/resources/LICENSE.md
@@ -0,0 +1,637 @@ +# Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + + 1. DEFINITIONS + + "Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + + "Contributor" means any person or entity that Distributes the Program. + + "Licensed Patents" mean patent claims licensable by a Contributor which + are necessarily infringed by the use or sale of its Contribution alone + or when combined with the Program. + + "Program" means the Contributions Distributed in accordance with this + Agreement. + + "Recipient" means anyone who receives the Program under this Agreement + or any Secondary License (as applicable), including Contributors. + + "Derivative Works" shall mean any work, whether in Source Code or other + form, that is based on (or derived from) the Program and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. + + "Modified Works" shall mean any work in Source Code or other form that + results from an addition to, deletion from, or modification of the + contents of the Program, including, for purposes of clarity any new file + in Source Code form that contains any contents of the Program. Modified + Works shall not include works that contain only declarations, + interfaces, types, classes, structures, or files of the Program solely + in each case in order to link to, bind by name, or subclass the Program + or Modified Works thereof. + + "Distribute" means the acts of a) distributing or b) making available + in any manner that enables the transfer of a copy. + + "Source Code" means the form of a Program preferred for making + modifications, including but not limited to software source code, + documentation source, and configuration files. + + "Secondary License" means either the GNU General Public License, + Version 2.0, or any later versions of that license, including any + exceptions or additional permissions as identified by the initial + Contributor. + + 2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + + 3. REQUIREMENTS + + 3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + + 3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + + 3.3 Contributors may not remove or alter any copyright, patent, + trademark, attribution notices, disclaimers of warranty, or limitations + of liability ("notices") contained within the Program from any copy of + the Program which they Distribute, provided that Contributors may add + their own appropriate notices. + + 4. COMMERCIAL DISTRIBUTION + + Commercial distributors of software may accept certain responsibilities + with respect to end users, business partners and the like. While this + license is intended to facilitate the commercial use of the Program, + the Contributor who includes the Program in a commercial product + offering should do so in a manner which does not create potential + liability for other Contributors. Therefore, if a Contributor includes + the Program in a commercial product offering, such Contributor + ("Commercial Contributor") hereby agrees to defend and indemnify every + other Contributor ("Indemnified Contributor") against any losses, + damages and costs (collectively "Losses") arising from claims, lawsuits + and other legal actions brought by a third party against the Indemnified + Contributor to the extent caused by the acts or omissions of such + Commercial Contributor in connection with its distribution of the Program + in a commercial product offering. The obligations in this section do not + apply to any claims or Losses relating to any actual or alleged + intellectual property infringement. In order to qualify, an Indemnified + Contributor must: a) promptly notify the Commercial Contributor in + writing of such claim, and b) allow the Commercial Contributor to control, + and cooperate with the Commercial Contributor in, the defense and any + related settlement negotiations. The Indemnified Contributor may + participate in any such claim at its own expense. + + For example, a Contributor might include the Program in a commercial + product offering, Product X. That Contributor is then a Commercial + Contributor. If that Commercial Contributor then makes performance + claims, or offers warranties related to Product X, those performance + claims and warranties are such Commercial Contributor's responsibility + alone. Under this section, the Commercial Contributor would have to + defend claims against the other Contributors related to those performance + claims and warranties, and if a court requires any other Contributor to + pay any damages as a result, the Commercial Contributor must pay + those damages. + + 5. NO WARRANTY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT + PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR + IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF + TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR + PURPOSE. Each Recipient is solely responsible for determining the + appropriateness of using and distributing the Program and assumes all + risks associated with its exercise of rights under this Agreement, + including but not limited to the risks and costs of program errors, + compliance with applicable laws, damage to or loss of data, programs + or equipment, and unavailability or interruption of operations. + + 6. DISCLAIMER OF LIABILITY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT + PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS + SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST + PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE + EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + + 7. GENERAL + + If any provision of this Agreement is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this Agreement, and without further + action by the parties hereto, such provision shall be reformed to the + minimum extent necessary to make such provision valid and enforceable. + + If Recipient institutes patent litigation against any entity + (including a cross-claim or counterclaim in a lawsuit) alleging that the + Program itself (excluding combinations of the Program with other software + or hardware) infringes such Recipient's patent(s), then such Recipient's + rights granted under Section 2(b) shall terminate as of the date such + litigation is filed. + + All Recipient's rights under this Agreement shall terminate if it + fails to comply with any of the material terms or conditions of this + Agreement and does not cure such failure in a reasonable period of + time after becoming aware of such noncompliance. If all Recipient's + rights under this Agreement terminate, Recipient agrees to cease use + and distribution of the Program as soon as reasonably practicable. + However, Recipient's obligations under this Agreement and any licenses + granted by Recipient relating to the Program shall continue and survive. + + Everyone is permitted to copy and distribute copies of this Agreement, + but in order to avoid inconsistency the Agreement is copyrighted and + may only be modified in the following manner. The Agreement Steward + reserves the right to publish new versions (including revisions) of + this Agreement from time to time. No one other than the Agreement + Steward has the right to modify this Agreement. The Eclipse Foundation + is the initial Agreement Steward. The Eclipse Foundation may assign the + responsibility to serve as the Agreement Steward to a suitable separate + entity. Each new version of the Agreement will be given a distinguishing + version number. The Program (including Contributions) may always be + Distributed subject to the version of the Agreement under which it was + received. In addition, after a new version of the Agreement is published, + Contributor may elect to Distribute the Program (including its + Contributions) under the new version. + + Except as expressly stated in Sections 2(a) and 2(b) above, Recipient + receives no rights or licenses to the intellectual property of any + Contributor under this Agreement, whether expressly, by implication, + estoppel or otherwise. All rights in the Program not expressly granted + under this Agreement are reserved. Nothing in this Agreement is intended + to be enforceable by any entity that is not a Contributor or Recipient. + No third-party beneficiary rights are created under this Agreement. + + Exhibit A - Form of Secondary Licenses Notice + + "This Source Code may also be made available under the following + Secondary Licenses when the conditions for such availability set forth + in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), + version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. + +--- + +## The GNU General Public License (GPL) Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor + Boston, MA 02110-1335 + USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your freedom to + share and change it. By contrast, the GNU General Public License is + intended to guarantee your freedom to share and change free software--to + make sure the software is free for all its users. This General Public + License applies to most of the Free Software Foundation's software and + to any other program whose authors commit to using it. (Some other Free + Software Foundation software is covered by the GNU Library General + Public License instead.) You can apply it to your programs, too. + + When we speak of free software, we are referring to freedom, not price. + Our General Public Licenses are designed to make sure that you have the + freedom to distribute copies of free software (and charge for this + service if you wish), that you receive source code or can get it if you + want it, that you can change the software or use pieces of it in new + free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid anyone + to deny you these rights or to ask you to surrender the rights. These + restrictions translate to certain responsibilities for you if you + distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether gratis + or for a fee, you must give the recipients all the rights that you have. + You must make sure that they, too, receive or can get the source code. + And you must show them these terms so they know their rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, we + want its recipients to know that what they have is not the original, so + that any problems introduced by others will not reflect on the original + authors' reputations. + + Finally, any free program is threatened constantly by software patents. + We wish to avoid the danger that redistributors of a free program will + individually obtain patent licenses, in effect making the program + proprietary. To prevent this, we have made it clear that any patent must + be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and + modification follow. + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed under + the terms of this General Public License. The "Program", below, refers + to any such program or work, and a "work based on the Program" means + either the Program or any derivative work under copyright law: that is + to say, a work containing the Program or a portion of it, either + verbatim or with modifications and/or translated into another language. + (Hereinafter, translation is included without limitation in the term + "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of running + the Program is not restricted, and the output from the Program is + covered only if its contents constitute a work based on the Program + (independent of having been made by running the Program). Whether that + is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's source + code as you receive it, in any medium, provided that you conspicuously + and appropriately publish on each copy an appropriate copyright notice + and disclaimer of warranty; keep intact all the notices that refer to + this License and to the absence of any warranty; and give any other + recipients of the Program a copy of this License along with the Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion of + it, thus forming a work based on the Program, and copy and distribute + such modifications or work under the terms of Section 1 above, provided + that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any part + thereof, to be licensed as a whole at no charge to all third parties + under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this License. + (Exception: if the Program itself is interactive but does not + normally print such an announcement, your work based on the Program + is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, and + can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based on + the Program, the distribution of the whole must be on the terms of this + License, whose permissions for other licensees extend to the entire + whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of a + storage or distribution medium does not bring the other work under the + scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your cost + of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed + only for noncommercial distribution and only if you received the + program in object code or executable form with such an offer, in + accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source code + means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to control + compilation and installation of the executable. However, as a special + exception, the source code distributed need not include anything that is + normally distributed (in either source or binary form) with the major + components (compiler, kernel, and so on) of the operating system on + which the executable runs, unless that component itself accompanies the + executable. + + If distribution of executable or object code is made by offering access + to copy from a designated place, then offering equivalent access to copy + the source code from the same place counts as distribution of the source + code, even though third parties are not compelled to copy the source + along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt otherwise + to copy, modify, sublicense or distribute the Program is void, and will + automatically terminate your rights under this License. However, parties + who have received copies, or rights, from you under this License will + not have their licenses terminated so long as such parties remain in + full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and all + its terms and conditions for copying, distributing or modifying the + Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further restrictions + on the recipients' exercise of the rights granted herein. You are not + responsible for enforcing compliance by third parties to this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot distribute + so as to satisfy simultaneously your obligations under this License and + any other pertinent obligations, then as a consequence you may not + distribute the Program at all. For example, if a patent license would + not permit royalty-free redistribution of the Program by all those who + receive copies directly or indirectly through you, then the only way you + could satisfy both it and this License would be to refrain entirely from + distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is implemented + by public license practices. Many people have made generous + contributions to the wide range of software distributed through that + system in reliance on consistent application of that system; it is up to + the author/donor to decide if he or she is willing to distribute + software through any other system and a licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be + a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License may + add an explicit geographical distribution limitation excluding those + countries, so that distribution is permitted only in or among countries + not thus excluded. In such case, this License incorporates the + limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", you have the option of following the terms and + conditions either of that version or of any later version published by + the Free Software Foundation. If the Program does not specify a version + number of this License, you may choose any version ever published by the + Free Software Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted by the + Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. + EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR + OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, + EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH + YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL + NECESSARY SERVICING, REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY + AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF + THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR + OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest to + attach them to the start of each source file to most effectively convey + the exclusion of warranty; and each file should have at least the + "copyright" line and a pointer to where the full notice is found. + + One line to give the program's name and a brief idea of what it does. + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA + + Also add information on how to contact you by electronic and paper mail. + + If the program is interactive, make it output a short notice like this + when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type + `show w'. This is free software, and you are welcome to redistribute + it under certain conditions; type `show c' for details. + + The hypothetical commands `show w' and `show c' should show the + appropriate parts of the General Public License. Of course, the commands + you use may be called something other than `show w' and `show c'; they + could even be mouse-clicks or menu items--whatever suits your program. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the program, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (which makes passes at compilers) written by + James Hacker. + + signature of Ty Coon, 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your program + into proprietary programs. If your program is a subroutine library, you + may consider it more useful to permit linking proprietary applications + with the library. If this is what you want to do, use the GNU Library + General Public License instead of this License. + +--- + +## CLASSPATH EXCEPTION + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License version 2 cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from or + based on this library. If you modify this library, you may extend this + exception to your version of the library, but you are not obligated to + do so. If you do not wish to do so, delete this exception statement + from your version.
diff --git a/bundles/ri/src/main/resources/README.txt b/bundles/ri/src/main/resources/README.txt new file mode 100644 index 0000000..7f7879f --- /dev/null +++ b/bundles/ri/src/main/resources/README.txt
@@ -0,0 +1,51 @@ +* standalone/jakarta.json-${project.version}.jar contains both Jakarta JSON Processing API + and its default provider implementation. Keep it in classpath for both compiling and running your application. + JPMS module name is: 'jakarta.json' + +For running on JPMS, following modules are provided: +* mods/jakarta.json-api-${project.version}.jar - 'jakarta.json' module containing only API classes +* mods/jakarta.json-${project.version}-module.jar - 'org.glassfish.jakarta.json' module containing implementation + +Integration with Jakarta RESTful Web Services: +* jaxrs/jsonp-jaxrs-${project.version}.jar + + +IMPORTANT NOTE: module names are not yet final and may change in the future releases + + +* If you are running with maven, you can use the following maven coordinates: + +for standalone reference implementation which includes APIs and implementation classes: + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + <version>${project.version}</version> + </dependency> + +for APIs: + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <version>${project.version}</version> + </dependency> + +for implementation only: + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + <classifier>module</classifier> + <version>${project.version}</version> + </dependency> + +for Jakarta RESTful Web Services integration module: + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jsonp-jaxrs</artifactId> + <version>${project.version}</version> + </dependency> + + +* GlassFish 6.x already bundles latest Jakarta JSON Processing implementation and Jakarta RESTful Web Services integration module. +If you deploy an application with GlassFish 6.x, your application (war/ear) doesn't have to bundle APIs nor the implementation jar. + +* Samples can be run from https://github.com/eclipse-ee4j/glassfish-samples
diff --git a/demos/LICENSE.md b/demos/LICENSE.md new file mode 100644 index 0000000..c739f78 --- /dev/null +++ b/demos/LICENSE.md
@@ -0,0 +1,29 @@ + + Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Eclipse Foundation, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/demos/NOTICE.md b/demos/NOTICE.md new file mode 100644 index 0000000..b4cb5ba --- /dev/null +++ b/demos/NOTICE.md
@@ -0,0 +1,49 @@ +# Notices for Eclipse Project for JSON Processing + +This content is produced and maintained by the Eclipse Project for JSON +Processing project. + +* Project home: https://projects.eclipse.org/projects/ee4j.jsonp + +## Trademarks + +Eclipse Project for JSON Processing is a trademark of the Eclipse Foundation. + +## Copyright + +All content is the property of the respective authors or their employers. For +more information regarding authorship of content, please consult the listed +source code repository logs. + +## Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License v. 2.0 which is available at +http://www.eclipse.org/legal/epl-2.0. This Source Code may also be made +available under the following Secondary Licenses when the conditions for such +availability set forth in the Eclipse Public License v. 2.0 are satisfied: GNU +General Public License, version 2 with the GNU Classpath Exception which is +available at https://www.gnu.org/software/classpath/license.html. + +SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +## Source Code + +The project maintains the following source code repositories: + +* https://github.com/eclipse-ee4j/jsonp + +## Third-party Content + +JUnit (4.12) + +* License: Eclipse Public License + +## Cryptography + +Content may contain encryption software. The country in which you are currently +may have restrictions on the import, possession, and use, and/or re-export to +another country, of encryption software. BEFORE using any encryption software, +please check the country's laws, regulations and policies concerning the import, +possession, or use, and re-export of encryption software, to see if this is +permitted.
diff --git a/demos/customprovider-jdk9/pom.xml b/demos/customprovider-jdk9/pom.xml new file mode 100644 index 0000000..73fb09d --- /dev/null +++ b/demos/customprovider-jdk9/pom.xml
@@ -0,0 +1,88 @@ +<!-- + + Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>demos</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <url>http://maven.apache.org</url> + <artifactId>customprovider-jdk9</artifactId> + + <name>customprovider-jdk9</name> + + <properties> + <mod.dir>${project.build.directory}/mods</mod.dir> + </properties> + <build> + <finalName>customprovider-jdk9</finalName> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>prepare-endorsed</id> + <phase>validate</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <outputDirectory>${mod.dir}</outputDirectory> + <silent>false</silent> + <!--<scope>compile</scope>--> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test</goal> + </goals> + <id>test</id> + </execution> + </executions> + <configuration> + <argLine> + --module-path ${project.build.directory}/classes:${mod.dir}:${project.build.directory}/test-classes + --add-modules org.glassfish.jakarta.json.demos.customprovider + </argLine> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-core</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project>
diff --git a/demos/customprovider-jdk9/src/main/java/module-info.java b/demos/customprovider-jdk9/src/main/java/module-info.java new file mode 100644 index 0000000..dfdd58a --- /dev/null +++ b/demos/customprovider-jdk9/src/main/java/module-info.java
@@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +module org.glassfish.jakarta.json.demos.customprovider { + requires transitive jakarta.json; + exports org.glassfish.json.customprovider; + provides jakarta.json.spi.JsonProvider with org.glassfish.json.customprovider.TestProvider; +}
diff --git a/demos/customprovider-jdk9/src/main/java/org/glassfish/json/customprovider/TestGenerator.java b/demos/customprovider-jdk9/src/main/java/org/glassfish/json/customprovider/TestGenerator.java new file mode 100644 index 0000000..ebe196f --- /dev/null +++ b/demos/customprovider-jdk9/src/main/java/org/glassfish/json/customprovider/TestGenerator.java
@@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.json.customprovider; + +import jakarta.json.JsonException; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerator; +import java.io.IOException; +import java.io.Writer; +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * @author Jitendra Kotamraju + */ +public class TestGenerator implements JsonGenerator { + private final Writer writer; + + public TestGenerator(Writer writer) { + this.writer = writer; + } + + @Override + public void flush() { + } + + @Override + public JsonGenerator writeStartObject() { + return null; + } + + @Override + public JsonGenerator writeStartObject(String name) { + return null; + } + + @Override + public JsonGenerator write(String name, String fieldValue) { + return null; + } + + @Override + public JsonGenerator write(String name, int value) { + return null; + } + + @Override + public JsonGenerator write(String name, long value) { + return null; + } + + @Override + public JsonGenerator write(String name, double value) { + return null; + } + + @Override + public JsonGenerator write(String name, BigInteger value) { + return null; + } + + @Override + public JsonGenerator write(String name, BigDecimal value) { + return null; + } + + @Override + public JsonGenerator write(String name, boolean value) { + return null; + } + + @Override + public JsonGenerator writeNull(String name) { + return null; + } + + @Override + public JsonGenerator write(JsonValue value) { + return null; + } + + @Override + public JsonGenerator writeStartArray() { + try { + writer.write("["); + } catch(IOException ioe) { + throw new JsonException("I/O error", ioe); + } + return this; + } + + @Override + public JsonGenerator writeStartArray(String name) { + return null; + } + + @Override + public JsonGenerator write(String name, JsonValue value) { + return null; + } + + @Override + public JsonGenerator write(String value) { + return null; + } + + + @Override + public JsonGenerator write(int value) { + return null; + } + + @Override + public JsonGenerator write(long value) { + return null; + } + + @Override + public JsonGenerator write(double value) { + return null; + } + + @Override + public JsonGenerator write(BigInteger value) { + return null; + } + + @Override + public JsonGenerator write(BigDecimal value) { + return null; + } + + @Override + public JsonGenerator write(boolean value) { + return null; + } + + @Override + public JsonGenerator writeNull() { + return null; + } + + @Override + public JsonGenerator writeEnd() { + try { + writer.write("]"); + } catch(IOException ioe) { + throw new JsonException("I/O error", ioe); + } + return this; + } + + @Override + public void close() { + try { + writer.close(); + } catch(IOException ioe) { + throw new JsonException("I/O error", ioe); + } + } + + @Override + public JsonGenerator writeKey(String string) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + +}
diff --git a/demos/customprovider-jdk9/src/main/java/org/glassfish/json/customprovider/TestProvider.java b/demos/customprovider-jdk9/src/main/java/org/glassfish/json/customprovider/TestProvider.java new file mode 100644 index 0000000..fe1fb76 --- /dev/null +++ b/demos/customprovider-jdk9/src/main/java/org/glassfish/json/customprovider/TestProvider.java
@@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.json.customprovider; + +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonGeneratorFactory; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParserFactory; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Map; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonReader; +import jakarta.json.JsonReaderFactory; +import jakarta.json.JsonWriter; +import jakarta.json.JsonWriterFactory; + +/** + * @author Jitendra Kotamraju + */ +public class TestProvider extends JsonProvider { + + @Override + public JsonGenerator createGenerator(Writer writer) { + return new TestGenerator(writer); + } + + @Override + public JsonGenerator createGenerator(OutputStream out) { + return new TestGenerator(new OutputStreamWriter(out)); + } + + @Override + public JsonGeneratorFactory createGeneratorFactory(Map<String, ?> config) { + return null; + } + + @Override + public JsonReader createReader(Reader reader) { + return null; + } + + @Override + public JsonReader createReader(InputStream in) { + return null; + } + + @Override + public JsonWriter createWriter(Writer writer) { + return null; + } + + @Override + public JsonWriter createWriter(OutputStream out) { + return null; + } + + @Override + public JsonWriterFactory createWriterFactory(Map<String, ?> config) { + return null; + } + + @Override + public JsonReaderFactory createReaderFactory(Map<String, ?> config) { + return null; + } + + @Override + public JsonObjectBuilder createObjectBuilder() { + return null; + } + + @Override + public JsonArrayBuilder createArrayBuilder() { + return null; + } + + @Override + public JsonBuilderFactory createBuilderFactory(Map<String, ?> config) { + return null; + } + + @Override + public JsonParser createParser(Reader reader) { + return null; + } + + @Override + public JsonParser createParser(InputStream in) { + return null; + } + + @Override + public JsonParserFactory createParserFactory(Map<String, ?> config) { + return null; + } + + +}
diff --git a/demos/customprovider-jdk9/src/test/java/customprovider/test/TestProviderTest.java b/demos/customprovider-jdk9/src/test/java/customprovider/test/TestProviderTest.java new file mode 100644 index 0000000..55c0a70 --- /dev/null +++ b/demos/customprovider-jdk9/src/test/java/customprovider/test/TestProviderTest.java
@@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package customprovider.test; + +import jakarta.json.Json; +import jakarta.json.stream.JsonGenerator; +import org.glassfish.json.customprovider.TestGenerator; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author lukas + */ +public class TestProviderTest { + + @Test + public void hello() { + try (JsonGenerator generator = Json.createGenerator(System.out)) { + Assert.assertTrue("TestGenerator is not picked up", generator instanceof TestGenerator); + generator.writeStartArray().writeEnd(); + } + System.out.println(); + System.out.println("Hurray!!!"); + } +}
diff --git a/demos/facebook/pom.xml b/demos/facebook/pom.xml new file mode 100644 index 0000000..8dc9048 --- /dev/null +++ b/demos/facebook/pom.xml
@@ -0,0 +1,101 @@ +<!-- + + Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>demos</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <packaging>jar</packaging> + <url>http://maven.apache.org</url> + <artifactId>jsondemos-facebook</artifactId> + + <properties> + <main.class>org.glassfish.jsondemos.facebook.FacebookObjectSearch</main.class> + <!-- + <main.class>org.glassfish.jsondemos.facebook.FacebookStreamSearch</main.class> + --> + <modules.directory>${project.build.directory}/modules</modules.directory> + </properties> + + <dependencies> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <configuration> + <stripVersion>true</stripVersion> + <outputDirectory>${modules.directory}</outputDirectory> + </configuration> + <executions> + <execution> + <id>get-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + </execution> + <execution> + <id>get-project-artifact</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <configuration> + <executable>java</executable> + <arguments> + <argument>--module-path</argument> + <argument>${modules.directory}</argument> + <argument>-m</argument> + <argument>org.glassfish.jakarta.json.demos.facebook/${main.class}</argument> + </arguments> + </configuration> + <executions> + <execution> + <id>example-facebook</id> + <goals> + <goal>exec</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project>
diff --git a/demos/facebook/src/main/java/module-info.java b/demos/facebook/src/main/java/module-info.java new file mode 100644 index 0000000..63f6774 --- /dev/null +++ b/demos/facebook/src/main/java/module-info.java
@@ -0,0 +1,13 @@ +/* + * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +module org.glassfish.jakarta.json.demos.facebook { + requires jakarta.json; +}
diff --git a/demos/facebook/src/main/java/org/glassfish/jsondemos/facebook/FacebookObjectSearch.java b/demos/facebook/src/main/java/org/glassfish/jsondemos/facebook/FacebookObjectSearch.java new file mode 100644 index 0000000..41114d1 --- /dev/null +++ b/demos/facebook/src/main/java/org/glassfish/jsondemos/facebook/FacebookObjectSearch.java
@@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.facebook; + +import jakarta.json.*; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Properties; + +/** + * Parses JSON from facebook graph API using object model API. + * JSON would like : + * + * { + * data: [ + * { "from" : { "name" : "xxx", ... }, "message: "yyy", ... }, + * { "from" : { "name" : "ppp", ... }, "message: "qqq", ... }, + * ... + * ], + * ... + * } + * + * This codes writes the facebook posts to output as follows: + * xxx: yyy + * -------- + * ppp: qqq + * -------- + * + * @author Jitendra Kotamraju + */ +public class FacebookObjectSearch { + + public static void main(String... args) throws Exception { + try (InputStream is = getSearchStream(); + JsonReader rdr = Json.createReader(is)) { + + JsonObject obj = rdr.readObject(); + JsonArray results = obj.getJsonArray("data"); + for (JsonObject result : results.getValuesAs(JsonObject.class)) { + JsonValue value = result.get("from"); + if (value != null && value instanceof JsonObject) { + System.out.print(((JsonObject)value).getString("name", "anon")); + } + System.out.print(": "); + System.out.println(result.getString("message", "")); + System.out.println("-----------"); + } + } + } + + static InputStream getSearchStream() throws Exception { + Properties config = new Properties(); + config.load(FacebookObjectSearch.class.getResourceAsStream( + "/facebookconfig.properties")); + final String accessToken = (String)config.get("access_token"); + + // Gets the search stream + String searchUrl = "https://graph.facebook.com/search?q=tamil&type=post&access_token="; + URL url = new URL(searchUrl+accessToken); + HttpURLConnection con = (HttpURLConnection)url.openConnection(); + return con.getInputStream(); + } + +}
diff --git a/demos/facebook/src/main/java/org/glassfish/jsondemos/facebook/FacebookStreamSearch.java b/demos/facebook/src/main/java/org/glassfish/jsondemos/facebook/FacebookStreamSearch.java new file mode 100644 index 0000000..be1aa88 --- /dev/null +++ b/demos/facebook/src/main/java/org/glassfish/jsondemos/facebook/FacebookStreamSearch.java
@@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.facebook; + +import jakarta.json.*; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import java.io.*; + +/** + * Parses JSON from facebook graph API using streaming API. + * JSON would like : + * + * { + * data: [ + * { "from" : { "name" : "xxx", ... }, "message: "yyy", ... }, + * { "from" : { "name" : "ppp", ... }, "message: "qqq", ... }, + * ... + * ], + * ... + * } + * + * This codes writes the facebook posts to output as follows: + * xxx: yyy + * -------- + * ppp: qqq + * -------- + * + * @author Jitendra Kotamraju + */ +public class FacebookStreamSearch { + + public static void main(String... args) throws Exception { + try (InputStream is = FacebookObjectSearch.getSearchStream(); + JsonParser parser = Json.createParser(is)) { + while (parser.hasNext()) { + Event e = parser.next(); + if (e == Event.KEY_NAME) { + switch (parser.getString()) { + case "name": + parser.next(); + System.out.print(parser.getString()); + System.out.print(": "); + break; + case "message": + parser.next(); + System.out.println(parser.getString()); + System.out.println("---------"); + break; + } + } + } + } + } + +}
diff --git a/demos/facebook/src/main/resources/facebookconfig.properties b/demos/facebook/src/main/resources/facebookconfig.properties new file mode 100644 index 0000000..f801f7d --- /dev/null +++ b/demos/facebook/src/main/resources/facebookconfig.properties
@@ -0,0 +1,12 @@ +# +# Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Distribution License v. 1.0, which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: BSD-3-Clause +# + + +access_token=
diff --git a/demos/jaxrs/pom.xml b/demos/jaxrs/pom.xml new file mode 100644 index 0000000..d907939 --- /dev/null +++ b/demos/jaxrs/pom.xml
@@ -0,0 +1,54 @@ +<!-- + + Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>demos</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <packaging>war</packaging> + <url>http://maven.apache.org</url> + <artifactId>jsondemos-jaxrs</artifactId> + + <name>jsondemos-jaxrs</name> + + <dependencies> + <dependency> + <groupId>jakarta.ws.rs</groupId> + <artifactId>jakarta.ws.rs-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + </plugin> + </plugins> + <finalName>jsondemos-jaxrs</finalName> + </build> +</project>
diff --git a/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/ArrayResource.java b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/ArrayResource.java new file mode 100644 index 0000000..8df6440 --- /dev/null +++ b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/ArrayResource.java
@@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.jaxrs; + +import jakarta.json.*; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; + +/** + * JsonArray as parameter and return type for a Jakarta RESTful Web Services resource + * + * @author Jitendra Kotamraju + */ +@Path("/array") +public class ArrayResource { + private static final JsonBuilderFactory bf = Json.createBuilderFactory(null); + + @GET + @Produces(MediaType.APPLICATION_JSON) + public JsonArray doGet() { + return bf.createArrayBuilder() + .add(bf.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(bf.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567")) + .build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + public void doPost(JsonArray structure) { + System.out.println(structure); + } + +}
diff --git a/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/DemoApplication.java b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/DemoApplication.java new file mode 100644 index 0000000..da8d87f --- /dev/null +++ b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/DemoApplication.java
@@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.jaxrs; + +import jakarta.json.stream.JsonGenerator; +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * A Jakarta RESTful Web Services Demo Application + * + * @author Jitendra Kotamraju + */ +@ApplicationPath("/") +public class DemoApplication extends Application { + + @Override + public Set<Class<?>> getClasses() { + Set<Class<?>> set = new HashSet<>(); + set.add(ParserResource.class); + set.add(GeneratorResource.class); + set.add(ObjectResource.class); + set.add(ArrayResource.class); + set.add(StructureResource.class); + + return set; + } + + @Override + public Map<String, Object> getProperties() { + return new HashMap<String, Object>() {{ + put(JsonGenerator.PRETTY_PRINTING, true); + }}; + } +}
diff --git a/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/GeneratorResource.java b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/GeneratorResource.java new file mode 100644 index 0000000..705a724 --- /dev/null +++ b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/GeneratorResource.java
@@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.jaxrs; + +import jakarta.json.Json; +import jakarta.json.stream.JsonGenerator; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.StreamingOutput; +import java.io.OutputStream; + +/** + * Writes wiki's JSON example in a streaming fashion using JsonGenerator + * + * @author Jitendra Kotamraju + */ +@Path("/generator") +public class GeneratorResource { + + @GET + @Produces(MediaType.APPLICATION_JSON) + public StreamingOutput doGet() { + return new StreamingOutput() { + public void write(OutputStream os) { + writeWikiExample(os); + } + }; + } + + // Writes wiki example JSON in a streaming fashion + private void writeWikiExample(OutputStream os) { + try(JsonGenerator gene = Json.createGenerator(os)) { + gene.writeStartObject() + .write("firstName", "John") + .write("lastName", "Smith") + .write("age", 25) + .writeStartObject("address") + .write("streetAddress", "21 2nd Street") + .write("city", "New York") + .write("state", "NY") + .write("postalCode", "10021") + .writeEnd() + .writeStartArray("phoneNumber") + .writeStartObject() + .write("type", "home") + .write("number", "212 555-1234") + .writeEnd() + .writeStartObject() + .write("type", "fax") + .write("number", "646 555-4567") + .writeEnd() + .writeEnd() + .writeEnd(); + } + } + +}
diff --git a/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/ObjectResource.java b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/ObjectResource.java new file mode 100644 index 0000000..c12eb35 --- /dev/null +++ b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/ObjectResource.java
@@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.jaxrs; + +import jakarta.json.*; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; + +/** + * JsonObject as parameter and return type for a + * Jakarta RESTful Web Services resource + * Writes a person's representation as JSON using JsonObject + * + * @author Jitendra Kotamraju + */ +@Path("/object") +public class ObjectResource { + private static final JsonBuilderFactory bf = Json.createBuilderFactory(null); + + @GET + @Produces(MediaType.APPLICATION_JSON) + public JsonObject doGet() { + return bf.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", bf.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", bf.createArrayBuilder() + .add(bf.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(bf.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + public void doPost(JsonObject structure) { + System.out.println(structure); + } + +}
diff --git a/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/ParserResource.java b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/ParserResource.java new file mode 100644 index 0000000..6809a4d --- /dev/null +++ b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/ParserResource.java
@@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.jaxrs; + +import jakarta.json.Json; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.StreamingOutput; +import java.io.*; +import java.net.URL; + +/** + * Filters JSON from flicker photo search REST API + * + * { + * photos : { + * photo: [ + * { id: "9889087315", secret: "40aeb70c83", server: "3818",farm: 4, ..}, + * { id: "9889087315", secret: "40aeb70c83", server: "3818",farm: 4, ..} + * ... + * ], + * ... + * } + * } + * + * @author Jitendra Kotamraju + */ +@Path("/parser") +public class ParserResource { + + @GET + @Produces("text/html") + public StreamingOutput doGet() { + return new StreamingOutput() { + public void write(OutputStream os) throws IOException { + writeFlickerFeed(os); + } + }; + } + + private void writeFlickerFeed(OutputStream os) throws IOException { + URL url = new URL("http://api.flickr.com/services/rest/?method=flickr.photos.getRecent&api_key=221160312e1c22ec60ecf336951b0e77&format=json&nojsoncallback=1&per_page=20"); + try(InputStream is = url.openStream(); + JsonParser parser = Json.createParser(is); + PrintWriter ps = new PrintWriter(new OutputStreamWriter(os, "UTF-8"))) { + String id = null; + String server = null; + String secret = null; + + ps.println("<html><body>"); + while(parser.hasNext()) { + Event e = parser.next(); + if (e == Event.KEY_NAME) { + String str = parser.getString(); + switch (str) { + case "id" : + parser.next(); + id = parser.getString(); + break; + case "farm" : + parser.next(); + String farm = parser.getString(); + ps.println("<img src=\"http://farm"+farm+".staticflickr.com/"+server+"/"+id+"_"+secret+".jpg\">"); + break; + case "server" : + parser.next(); + server = parser.getString(); + break; + case "secret" : + parser.next(); + secret = parser.getString(); + break; + } + } + } + ps.println("</body></html>"); + ps.flush(); + } + } + +}
diff --git a/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/StructureResource.java b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/StructureResource.java new file mode 100644 index 0000000..b1ce73c --- /dev/null +++ b/demos/jaxrs/src/main/java/org/glassfish/jsondemos/jaxrs/StructureResource.java
@@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.jaxrs; + +import jakarta.json.*; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; + +/** + * JsonStructure as parameter and return type for a + * Jakarta RESTful Web Services resource + * + * @author Jitendra Kotamraju + */ +@Path("/structure") +public class StructureResource { + private static final JsonBuilderFactory bf = Json.createBuilderFactory(null); + + @GET + @Produces(MediaType.APPLICATION_JSON) + public JsonStructure doGet() { + return bf.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", bf.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", bf.createArrayBuilder() + .add(bf.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(bf.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + public void doPost(JsonStructure structure) { + System.out.println(structure); + } + +}
diff --git a/demos/jsonpointer/pom.xml b/demos/jsonpointer/pom.xml new file mode 100644 index 0000000..d32c252 --- /dev/null +++ b/demos/jsonpointer/pom.xml
@@ -0,0 +1,105 @@ +<!-- + + Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>demos</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <packaging>jar</packaging> + <url>http://maven.apache.org</url> + <artifactId>jsondemos-jsonpointer</artifactId> + + <properties> + <main.class>org.glassfish.jsondemos.jsonpointer.JsonpointerDemo</main.class> + <modules.directory>${project.build.directory}/modules</modules.directory> + </properties> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + <classifier>module</classifier> + <scope>compile</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <configuration> + <stripVersion>true</stripVersion> + <outputDirectory>${modules.directory}</outputDirectory> + </configuration> + <executions> + <execution> + <id>get-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + </execution> + <execution> + <id>get-project-artifact</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <configuration> + <executable>java</executable> + <arguments> + <argument>--module-path</argument> + <argument>${modules.directory}</argument> + <argument>-m</argument> + <argument>org.glassfish.jakarta.json.demos.jsonpointer/${main.class}</argument> + </arguments> + </configuration> + <executions> + <execution> + <id>example-jsonpointer</id> + <phase>verify</phase> + <goals> + <goal>exec</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project>
diff --git a/demos/jsonpointer/src/main/java/module-info.java b/demos/jsonpointer/src/main/java/module-info.java new file mode 100644 index 0000000..b14fa4a --- /dev/null +++ b/demos/jsonpointer/src/main/java/module-info.java
@@ -0,0 +1,13 @@ +/* + * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +module org.glassfish.jakarta.json.demos.jsonpointer { + requires jakarta.json; +}
diff --git a/demos/jsonpointer/src/main/java/org/glassfish/jsondemos/jsonpointer/JsonpointerDemo.java b/demos/jsonpointer/src/main/java/org/glassfish/jsondemos/jsonpointer/JsonpointerDemo.java new file mode 100644 index 0000000..4236a0f --- /dev/null +++ b/demos/jsonpointer/src/main/java/org/glassfish/jsondemos/jsonpointer/JsonpointerDemo.java
@@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.jsonpointer; + +import java.io.IOException; +import java.io.InputStream; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; + +/** + * JsonPointer (http://tools.ietf.org/html/rfc6901) demo with object model API + * + * @author Jitendra Kotamraju + */ +public class JsonpointerDemo { + + public static void main(String... args) throws Exception { + testWiki(); + testPointer(); + System.out.println("Both tests PASSED !!!"); + } + + private static void testWiki() throws IOException { + try (InputStream is = JsonpointerDemo.class.getResourceAsStream("/wiki.json"); + JsonReader rdr = Json.createReader(is)) { + JsonObject person = rdr.readObject(); + + assertEquals("NY", getString(person, "/address/state")); + assertEquals("212 555-1234", getString(person, "/phoneNumber/0/number")); + } + } + + private static void testPointer() throws IOException { + try (InputStream is = JsonpointerDemo.class.getResourceAsStream("/jsonpointer.json"); + JsonReader rdr = Json.createReader(is)) { + JsonObject root = rdr.readObject(); + + assertEquals(root, get(root, "")); + assertEquals(root.get("foo"), get(root, "/foo")); + assertEquals(root.getJsonArray("foo").get(0), get(root, "/foo/0")); + assertEquals(root.get(""), get(root, "/")); + assertEquals(root.get("a/b"), get(root, "/a~1b")); + assertEquals(root.get("c%d"), get(root, "/c%d")); + assertEquals(root.get("e^f"), get(root, "/e^f")); + assertEquals(root.get("k\"l"), get(root, "/k\"l")); + assertEquals(root.get("i\\j"), get(root, "/i\\j")); + assertEquals(root.get(" "), get(root, "/ ")); + assertEquals(root.get("m~n"), get(root, "/m~0n")); + + // Adding a parent to current root and try with it + JsonObject doc = Json.createObjectBuilder().add("doc", root).build(); + root = doc.getJsonObject("doc"); + assertEquals(doc, get(doc, "")); + assertEquals(root.get("foo"), get(doc, "/doc/foo")); + assertEquals(root.getJsonArray("foo").get(0), get(doc, "/doc/foo/0")); + assertEquals(root.get(""), get(doc, "/doc/")); + assertEquals(root.get("a/b"), get(doc, "/doc/a~1b")); + assertEquals(root.get("c%d"), get(doc, "/doc/c%d")); + assertEquals(root.get("e^f"), get(doc, "/doc/e^f")); + assertEquals(root.get("k\"l"), get(doc, "/doc/k\"l")); + assertEquals(root.get("i\\j"), get(doc, "/doc/i\\j")); + assertEquals(root.get(" "), get(doc, "/doc/ ")); + assertEquals(root.get("m~n"), get(doc, "/doc/m~0n")); + } + } + + private static String getString(JsonValue root, String pointer) { + return ((JsonString)get(root, pointer)).getString(); + } + + private static JsonValue get(JsonValue root, String pointer) { + if (pointer.isEmpty()) { + return root; + } + if (pointer.charAt(0) != '/') { + throw new IllegalArgumentException( + "JsonPointer "+pointer+" doesn't start with /"); + } + + StringBuilder referenceToken = new StringBuilder(); + for(int i=1; i < pointer.length(); i++) { // 1 to skip first / + char ch = pointer.charAt(i); + if (ch == '/') { + return get(newRoot(root, referenceToken.toString()), pointer.substring(i)); + } else if (ch == '~') { + // handle escaping ~0, ~1 + if (i+1 == pointer.length()) { + throw new IllegalArgumentException("Illegal escaping: expected ~0 or ~1, but got only ~ in pointer="+pointer); + } + ch = pointer.charAt(++i); + if (ch == '0') { + referenceToken.append('~'); + } else if (ch == '1') { + referenceToken.append('/'); + } else { + throw new IllegalArgumentException("Illegal escaping: expected ~0 or ~1, but got ~"+ch+" in pointer="+pointer); + } + } else { + referenceToken.append(ch); + } + } + return newRoot(root, referenceToken.toString()); + } + + private static JsonValue newRoot(JsonValue root, String referenceToken) { + if (root instanceof JsonObject) { + return ((JsonObject)root).get(referenceToken); + } else if (root instanceof JsonArray) { + return ((JsonArray)root).get(Integer.parseInt(referenceToken)); + } + throw new IllegalArgumentException("Illegal reference token="+referenceToken+" for value="+root); + } + + private static void assertEquals(JsonValue exp, JsonValue got) { + if (exp != got) { + throw new RuntimeException("Expected = "+exp+" but got = "+got); + } + } + + private static void assertEquals(String exp, String got) { + if (!exp.equals(got)) { + throw new RuntimeException("Expected = "+exp+" but got = "+got); + } + } + +}
diff --git a/demos/jsonpointer/src/main/resources/jsonpointer.json b/demos/jsonpointer/src/main/resources/jsonpointer.json new file mode 100644 index 0000000..937a098 --- /dev/null +++ b/demos/jsonpointer/src/main/resources/jsonpointer.json
@@ -0,0 +1,12 @@ +{ + "foo": ["bar", "baz"], + "": 0, + "a/b": 1, + "c%d": 2, + "e^f": 3, + "g|h": 4, + "i\\j": 5, + "k\"l": 6, + " ": 7, + "m~n": 8 +}
diff --git a/demos/jsonpointer/src/main/resources/wiki.json b/demos/jsonpointer/src/main/resources/wiki.json new file mode 100644 index 0000000..17bb193 --- /dev/null +++ b/demos/jsonpointer/src/main/resources/wiki.json
@@ -0,0 +1,21 @@ +{ + "firstName": "John", + "lastName": "Smith", + "age": 25, + "address": { + "streetAddress": "21 2nd Street", + "city": "New York", + "state": "NY", + "postalCode": "10021" + }, + "phoneNumber": [ + { + "type": "home", + "number": "212 555-1234" + }, + { + "type": "fax", + "number": "646 555-4567" + } + ] +}
diff --git a/demos/pom.xml b/demos/pom.xml new file mode 100644 index 0000000..6107d19 --- /dev/null +++ b/demos/pom.xml
@@ -0,0 +1,41 @@ +<!-- + + Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish</groupId> + <artifactId>json</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <packaging>pom</packaging> + <url>http://maven.apache.org</url> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>demos</artifactId> + + <properties> + <legal.doc.source>${basedir}/..</legal.doc.source> + </properties> + + <modules> + <module>jaxrs</module> + <module>twitter</module> + <module>facebook</module> + <module>jsonpointer</module> + <module>servlet</module> + <module>customprovider-jdk9</module> + </modules> + +</project>
diff --git a/demos/servlet/pom.xml b/demos/servlet/pom.xml new file mode 100644 index 0000000..35a337a --- /dev/null +++ b/demos/servlet/pom.xml
@@ -0,0 +1,54 @@ +<!-- + + Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>demos</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <packaging>war</packaging> + <url>http://maven.apache.org</url> + <artifactId>jsondemos-servlet</artifactId> + + <name>jsondemos-servlet</name> + + <dependencies> + <dependency> + <groupId>jakarta.servlet</groupId> + <artifactId>jakarta.servlet-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + </plugin> + </plugins> + <finalName>jsondemos-servlet</finalName> + </build> +</project>
diff --git a/demos/servlet/src/main/java/org/glassfish/jsondemos/servlet/ArrayServlet.java b/demos/servlet/src/main/java/org/glassfish/jsondemos/servlet/ArrayServlet.java new file mode 100644 index 0000000..9cac18f --- /dev/null +++ b/demos/servlet/src/main/java/org/glassfish/jsondemos/servlet/ArrayServlet.java
@@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.servlet; + +import java.io.IOException; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonWriter; +import jakarta.json.JsonWriterFactory; + +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +/** + * Writes a JsonArray using HttpServletResponse#getWriter + * http://localhost:8080/jsondemos-servlet/array + * + * Writes a JsonArray using HttpServletResponse#getOutputStream + * http://localhost:8080/jsondemos-servlet/array?stream + * + * + * @author Jitendra Kotamraju + */ +@WebServlet("/array") +public class ArrayServlet extends HttpServlet { + private static final JsonBuilderFactory bf = Json.createBuilderFactory(null); + private static final JsonWriterFactory wf = Json.createWriterFactory(null); + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException { + JsonArray array = bf.createArrayBuilder() + .add(bf.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(bf.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567")) + .build(); + res.setStatus(HttpServletResponse.SC_OK); + res.setContentType("application/json"); + res.setCharacterEncoding("UTF-8"); + + String q = req.getQueryString(); + boolean isStream = q != null && q.equals("stream"); + JsonWriter writer = isStream + ? wf.createWriter(res.getOutputStream()) + : wf.createWriter(res.getWriter()); + writer.write(array); + // not closing writer intentionally + } + +}
diff --git a/demos/twitter/pom.xml b/demos/twitter/pom.xml new file mode 100644 index 0000000..8ce39fa --- /dev/null +++ b/demos/twitter/pom.xml
@@ -0,0 +1,120 @@ +<!-- + + Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>demos</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <packaging>jar</packaging> + <url>http://maven.apache.org</url> + <artifactId>jsondemos-twitter</artifactId> + + <properties> + <main.class>org.glassfish.jsondemos.twitter.TwitterObjectSearch</main.class> + <!-- + <main.class>org.glassfish.jsondemos.twitter.TwitterStreamSearch</main.class> + --> + <modules.directory>${project.build.directory}/modules</modules.directory> + </properties> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + <classifier>module</classifier> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>jakarta.xml.bind</groupId> + <artifactId>jakarta.xml.bind-api</artifactId> + </dependency> + <dependency> + <groupId>com.sun.xml.bind</groupId> + <artifactId>jaxb-impl</artifactId> + <scope>runtime</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <configuration> + <stripVersion>true</stripVersion> + <outputDirectory>${modules.directory}</outputDirectory> + </configuration> + <executions> + <execution> + <id>get-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <excludeArtifactIds>jakarta.activation-api</excludeArtifactIds> + </configuration> + </execution> + <execution> + <id>get-project-artifact</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <configuration> + <executable>java</executable> + <arguments> + <argument>--module-path</argument> + <argument>${modules.directory}</argument> + <argument>-m</argument> + <argument>org.glassfish.jakarta.json.demos.twitter/${main.class}</argument> + </arguments> + </configuration> + <executions> + <execution> + <id>example-twitter</id> + <goals> + <goal>exec</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project>
diff --git a/demos/twitter/src/main/java/module-info.java b/demos/twitter/src/main/java/module-info.java new file mode 100644 index 0000000..1996e3e --- /dev/null +++ b/demos/twitter/src/main/java/module-info.java
@@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +module org.glassfish.jakarta.json.demos.twitter { + requires jakarta.xml.bind; + requires jakarta.json; +}
diff --git a/demos/twitter/src/main/java/org/glassfish/jsondemos/twitter/TwitterObjectSearch.java b/demos/twitter/src/main/java/org/glassfish/jsondemos/twitter/TwitterObjectSearch.java new file mode 100644 index 0000000..6538140 --- /dev/null +++ b/demos/twitter/src/main/java/org/glassfish/jsondemos/twitter/TwitterObjectSearch.java
@@ -0,0 +1,150 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.twitter; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import jakarta.json.*; +import jakarta.xml.bind.DatatypeConverter; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.*; + +/** + * Parses JSON from twitter search REST API using object model API. + * JSON would like : + * + * { + " statuses": [ + * { ..., "user" : { "name" : "xxx", ...}, "text: "yyy", ... }, + * { ..., "user" : { "name" : "ppp", ...}, "text: "qqq", ... }, + * ... + * ], + * ... + * } + * + * This codes writes the tweets to output as follows: + * xxx: yyy + * -------- + * ppp: qqq + * -------- + * + * @author Jitendra Kotamraju + */ +public class TwitterObjectSearch { + + public static void main(String... args) throws Exception { + try (InputStream is = getSearchStream(); + JsonReader rdr = Json.createReader(is)) { + + JsonObject obj = rdr.readObject(); + JsonArray results = obj.getJsonArray("statuses"); + for (JsonObject result : results.getValuesAs(JsonObject.class)) { + System.out.print(result.getJsonObject("user").getString("name", "anonymous")); + System.out.print(": "); + System.out.println(result.get("text")); + System.out.println("-----------"); + } + +// All the tweets are collected into Stream<String> and printed +// obj.getJsonArray("statuses").getValuesAs(JsonObject.class) +// .stream() +// .map(v -> v.getString("text")) +// .forEach(s -> { System.out.println(s); } ); + } + } + + static InputStream getSearchStream() throws Exception { + final String searchStr = "#javaone"; + String searchUrl = "https://api.twitter.com/1.1/search/tweets.json"; + + Properties config = new Properties(); + config.load(TwitterObjectSearch.class.getResourceAsStream( + "/twitterconfig.properties")); + + final String consumerKey = (String)config.get("consumer-key"); + final String consumerSecret = (String)config.get("consumer-secret"); + final String accessToken = (String)config.get("access-token"); + final String accessTokenSecret = (String)config.get("access-token-secret"); + final int timestamp = (int)(System.currentTimeMillis()/1000); + + Map<String, String> map = new TreeMap<String, String>() {{ + put("count", "100"); + put("oauth_consumer_key", consumerKey); + put("oauth_nonce", "4b25256957d75b6370f33a4501dc5e7e"); // TODO + put("oauth_signature_method", "HMAC-SHA1"); + put("oauth_timestamp", ""+timestamp); + put("oauth_token", accessToken); + put("oauth_version", "1.0"); + put("q", searchStr); + }}; + + // Builds param string + StringBuilder paramsBuilder = new StringBuilder(); + boolean first = true; + for(Map.Entry<String, String> e : map.entrySet()) { + if (!first) { + paramsBuilder.append('&'); + } + first = false; + paramsBuilder.append(e.getKey()); + paramsBuilder.append("="); + paramsBuilder.append(URLEncoder.encode(e.getValue(), "UTF-8")); + } + String paramsString = paramsBuilder.toString(); + + // builds signature string + StringBuilder signatureBuilder = new StringBuilder(); + signatureBuilder.append("GET"); + signatureBuilder.append('&'); + signatureBuilder.append(URLEncoder.encode(searchUrl, "UTF-8")); + signatureBuilder.append('&'); + signatureBuilder.append(URLEncoder.encode(paramsString, "UTF-8")); + String signatureBasedString = signatureBuilder.toString(); + + // Create authorization signature + Mac m = Mac.getInstance("HmacSHA1"); + m.init(new SecretKeySpec((consumerSecret+"&"+accessTokenSecret).getBytes(), "HmacSHA1")); + m.update(signatureBasedString.getBytes()); + byte[] res = m.doFinal(); + final String oauthSig = URLEncoder.encode(DatatypeConverter.printBase64Binary(res), "UTF-8"); + map.put("oauth_signature", oauthSig); + map.remove("count"); + map.remove("q"); + + // Build Authorization header + StringBuilder authorizationBuilder = new StringBuilder(); + authorizationBuilder.append("OAuth "); + first = true; + for(Map.Entry<String, String> e : map.entrySet()) { + if (!first) { + authorizationBuilder.append(','); + authorizationBuilder.append(' '); + } + first = false; + authorizationBuilder.append(e.getKey()); + authorizationBuilder.append('='); + authorizationBuilder.append('"'); + authorizationBuilder.append(e.getValue()); + authorizationBuilder.append('"'); + } + + // Gets the search stream + URL url = new URL(searchUrl+"?q="+URLEncoder.encode(searchStr, "UTF-8")+ + "&count=100"); + HttpURLConnection con = (HttpURLConnection)url.openConnection(); + con.addRequestProperty("Authorization", authorizationBuilder.toString()); + return con.getInputStream(); + } + +}
diff --git a/demos/twitter/src/main/java/org/glassfish/jsondemos/twitter/TwitterStreamSearch.java b/demos/twitter/src/main/java/org/glassfish/jsondemos/twitter/TwitterStreamSearch.java new file mode 100644 index 0000000..1271655 --- /dev/null +++ b/demos/twitter/src/main/java/org/glassfish/jsondemos/twitter/TwitterStreamSearch.java
@@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jsondemos.twitter; + +import jakarta.json.*; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import java.io.*; + +/** + * Parses JSON from twitter search REST API using streaming API. + * JSON would like : + * + * { + " statuses": [ + * { ..., "user" : { "name" : "xxx", ...}, "text: "yyy", ... }, + * { ..., "user" : { "name" : "ppp", ...}, "text: "qqq", ... }, + * ... + * ], + * ... + * } + * + * This codes writes the tweets to output as follows: + * xxx: yyy + * -------- + * ppp: qqq + * -------- + * + * TODO need to do better, also the last tweet is repeated ! + * + * @author Jitendra Kotamraju + */ +public class TwitterStreamSearch { + + public static void main(String... args) throws Exception { + try (InputStream is = TwitterObjectSearch.getSearchStream(); + JsonParser parser = Json.createParser(is)) { + int depth = 0; + String name = null; + String text = null; + while (parser.hasNext()) { + Event e = parser.next(); + if (e == Event.KEY_NAME) { + switch (parser.getString()) { + case "name": + if (depth == 3) { + parser.next(); + name = parser.getString(); + } + break; + case "text": + if (depth == 2) { + parser.next(); + text = parser.getString(); + } + break; + } + } else if (e == Event.START_OBJECT) { + ++depth; + } else if (e == Event.END_OBJECT) { + --depth; + if (depth == 1) { + System.out.println(name+": "+text); + System.out.println("-----------"); + + } + } + } + } + } + +}
diff --git a/demos/twitter/src/main/resources/twitterconfig.properties b/demos/twitter/src/main/resources/twitterconfig.properties new file mode 100644 index 0000000..87b5d72 --- /dev/null +++ b/demos/twitter/src/main/resources/twitterconfig.properties
@@ -0,0 +1,16 @@ +# +# Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Distribution License v. 1.0, which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: BSD-3-Clause +# + + +consumer-key= +consumer-secret= +access-token= +access-token-secret= +
diff --git a/etc/config/copyright-exclude b/etc/config/copyright-exclude new file mode 100644 index 0000000..e7f6f88 --- /dev/null +++ b/etc/config/copyright-exclude
@@ -0,0 +1,8 @@ +.json +.md +speclicense.html +MANIFEST.MF +/META-INF/services/ +/etc/config/copyright-exclude +/etc/config/copyright.txt +/bundles/ri/src/main/resources/README.txt
diff --git a/etc/config/copyright.txt b/etc/config/copyright.txt new file mode 100644 index 0000000..9c347b6 --- /dev/null +++ b/etc/config/copyright.txt
@@ -0,0 +1,15 @@ +/* + * Copyright (c) YYYY Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */
diff --git a/etc/config/exclude.xml b/etc/config/exclude.xml new file mode 100644 index 0000000..7380f9d --- /dev/null +++ b/etc/config/exclude.xml
@@ -0,0 +1,14 @@ +<!-- + + Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<FindBugsFilter> +</FindBugsFilter>
diff --git a/gf/customprovider/pom.xml b/gf/customprovider/pom.xml new file mode 100644 index 0000000..f472eb6 --- /dev/null +++ b/gf/customprovider/pom.xml
@@ -0,0 +1,38 @@ +<!-- + + Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>providers</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <packaging>war</packaging> + <url>http://maven.apache.org</url> + <artifactId>customprovider</artifactId> + + <name>customprovider</name> + + <build> + <finalName>customprovider</finalName> + </build> +</project>
diff --git a/gf/customprovider/src/main/java/org/glassfish/json/customprovider/TestGenerator.java b/gf/customprovider/src/main/java/org/glassfish/json/customprovider/TestGenerator.java new file mode 100644 index 0000000..c11f013 --- /dev/null +++ b/gf/customprovider/src/main/java/org/glassfish/json/customprovider/TestGenerator.java
@@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.customprovider; + +import jakarta.json.JsonException; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerator; +import java.io.IOException; +import java.io.Writer; +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * @author Jitendra Kotamraju + */ +public class TestGenerator implements JsonGenerator { + private final Writer writer; + + public TestGenerator(Writer writer) { + this.writer = writer; + } + + @Override + public void flush() { + } + + @Override + public JsonGenerator writeStartObject() { + return null; + } + + @Override + public JsonGenerator writeStartObject(String name) { + return null; + } + + @Override + public JsonGenerator write(String name, String fieldValue) { + return null; + } + + @Override + public JsonGenerator write(String name, int value) { + return null; + } + + @Override + public JsonGenerator write(String name, long value) { + return null; + } + + @Override + public JsonGenerator write(String name, double value) { + return null; + } + + @Override + public JsonGenerator write(String name, BigInteger value) { + return null; + } + + @Override + public JsonGenerator write(String name, BigDecimal value) { + return null; + } + + @Override + public JsonGenerator write(String name, boolean value) { + return null; + } + + @Override + public JsonGenerator writeNull(String name) { + return null; + } + + @Override + public JsonGenerator write(JsonValue value) { + return null; + } + + @Override + public JsonGenerator writeStartArray() { + try { + writer.write("["); + } catch(IOException ioe) { + throw new JsonException("I/O error", ioe); + } + return this; + } + + @Override + public JsonGenerator writeStartArray(String name) { + return null; + } + + @Override + public JsonGenerator write(String name, JsonValue value) { + return null; + } + + @Override + public JsonGenerator write(String value) { + return null; + } + + + @Override + public JsonGenerator write(int value) { + return null; + } + + @Override + public JsonGenerator write(long value) { + return null; + } + + @Override + public JsonGenerator write(double value) { + return null; + } + + @Override + public JsonGenerator write(BigInteger value) { + return null; + } + + @Override + public JsonGenerator write(BigDecimal value) { + return null; + } + + @Override + public JsonGenerator write(boolean value) { + return null; + } + + @Override + public JsonGenerator writeNull() { + return null; + } + + @Override + public JsonGenerator writeEnd() { + try { + writer.write("]"); + } catch(IOException ioe) { + throw new JsonException("I/O error", ioe); + } + return this; + } + + @Override + public void close() { + try { + writer.close(); + } catch(IOException ioe) { + throw new JsonException("I/O error", ioe); + } + } + + @Override + public JsonGenerator writeKey(String name) { + return null; + } + +}
diff --git a/gf/customprovider/src/main/java/org/glassfish/json/customprovider/TestProvider.java b/gf/customprovider/src/main/java/org/glassfish/json/customprovider/TestProvider.java new file mode 100644 index 0000000..ee1ffcb --- /dev/null +++ b/gf/customprovider/src/main/java/org/glassfish/json/customprovider/TestProvider.java
@@ -0,0 +1,112 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.customprovider; + +import jakarta.json.*; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonGeneratorFactory; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParserFactory; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Map; + +/** + * @author Jitendra Kotamraju + */ +public class TestProvider extends JsonProvider { + + @Override + public JsonGenerator createGenerator(Writer writer) { + return new TestGenerator(writer); + } + + @Override + public JsonGenerator createGenerator(OutputStream out) { + return null; + } + + @Override + public JsonGeneratorFactory createGeneratorFactory(Map<String, ?> config) { + return null; + } + + @Override + public JsonReader createReader(Reader reader) { + return null; + } + + @Override + public JsonReader createReader(InputStream in) { + return null; + } + + @Override + public JsonWriter createWriter(Writer writer) { + return null; + } + + @Override + public JsonWriter createWriter(OutputStream out) { + return null; + } + + @Override + public JsonWriterFactory createWriterFactory(Map<String, ?> config) { + return null; + } + + @Override + public JsonReaderFactory createReaderFactory(Map<String, ?> config) { + return null; + } + + @Override + public JsonObjectBuilder createObjectBuilder() { + return null; + } + + @Override + public JsonArrayBuilder createArrayBuilder() { + return null; + } + + @Override + public JsonBuilderFactory createBuilderFactory(Map<String, ?> config) { + return null; + } + + @Override + public JsonParser createParser(Reader reader) { + return null; + } + + @Override + public JsonParser createParser(InputStream in) { + return null; + } + + @Override + public JsonParserFactory createParserFactory(Map<String, ?> config) { + return null; + } + + +}
diff --git a/gf/customprovider/src/main/java/org/glassfish/json/customprovider/TestServlet.java b/gf/customprovider/src/main/java/org/glassfish/json/customprovider/TestServlet.java new file mode 100644 index 0000000..38bd1d4 --- /dev/null +++ b/gf/customprovider/src/main/java/org/glassfish/json/customprovider/TestServlet.java
@@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.customprovider; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import jakarta.json.Json; +import jakarta.json.stream.JsonGenerator; + +/** + * @author Jitendra Kotamraju + */ +@WebServlet("/json") +public class TestServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException { + try { + res.setStatus(200); + res.setContentType("application/json"); + OutputStream os = res.getOutputStream(); + JsonGenerator generator = Json.createGenerator(new OutputStreamWriter(os)); + if (!(generator instanceof TestGenerator)) { + throw new RuntimeException("MyGenerator is not picked up"); + } + generator.writeStartArray().writeEnd(); + generator.close(); + os.close(); + } catch (IOException ioe) { + throw new ServletException(ioe); + } + } + +}
diff --git a/gf/customprovider/src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider b/gf/customprovider/src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider new file mode 100644 index 0000000..0647df2 --- /dev/null +++ b/gf/customprovider/src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider
@@ -0,0 +1 @@ +org.glassfish.json.customprovider.TestProvider
diff --git a/gf/defaultprovider/pom.xml b/gf/defaultprovider/pom.xml new file mode 100644 index 0000000..e1199af --- /dev/null +++ b/gf/defaultprovider/pom.xml
@@ -0,0 +1,38 @@ +<!-- + + Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>providers</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <packaging>war</packaging> + <url>http://maven.apache.org</url> + <artifactId>defaultprovider</artifactId> + + <name>defaultprovider</name> + + <build> + <finalName>defaultprovider</finalName> + </build> +</project>
diff --git a/gf/defaultprovider/src/main/java/org/glassfish/json/defaultprovider/TestServlet.java b/gf/defaultprovider/src/main/java/org/glassfish/json/defaultprovider/TestServlet.java new file mode 100644 index 0000000..ac58dd5 --- /dev/null +++ b/gf/defaultprovider/src/main/java/org/glassfish/json/defaultprovider/TestServlet.java
@@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.defaultprovider; + +import jakarta.servlet.annotation.*; +import jakarta.servlet.http.*; +import jakarta.servlet.*; +import java.io.IOException; +import jakarta.json.*; +import jakarta.json.stream.*; +import java.io.*; + +/** + * @author Jitendra Kotamraju + */ +@WebServlet("/json") +public class TestServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException { + try { + res.setStatus(200); + res.setContentType("application/json"); + OutputStream os = res.getOutputStream(); + JsonGenerator generator = Json.createGenerator(os); + generator.writeStartArray().writeEnd(); + generator.close(); + } catch(IOException ioe) { + throw new ServletException(ioe); + } + } + +}
diff --git a/gf/pom.xml b/gf/pom.xml new file mode 100644 index 0000000..c85e902 --- /dev/null +++ b/gf/pom.xml
@@ -0,0 +1,59 @@ +<!-- + + Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish</groupId> + <artifactId>json</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <packaging>pom</packaging> + <url>http://maven.apache.org</url> + <groupId>org.glassfish.jsonp</groupId> + <artifactId>providers</artifactId> + + <dependencies> + <dependency> + <groupId>jakarta.servlet</groupId> + <artifactId>jakarta.servlet-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + </plugin> + </plugins> + <finalName>customprovider</finalName> + </build> + <modules> + <module>customprovider</module> + <module>defaultprovider</module> + </modules> +</project>
diff --git a/impl-tck/pom.xml b/impl-tck/pom.xml new file mode 100644 index 0000000..7f24ba8 --- /dev/null +++ b/impl-tck/pom.xml
@@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json-tck</artifactId> + <version>1.0.0-SNAPSHOT</version> + <packaging>pom</packaging> + + <modules> + <module>tck-tests</module> + <module>tck-tests-plugability</module> + </modules> + + <properties> + <jsonp-api.version>2.0.0-SNAPSHOT</jsonp-api.version> + <jsonp-impl.version>2.0.0-SNAPSHOT</jsonp-impl.version> + <jsonp-tck.version>2.0.0-SNAPSHOT</jsonp-tck.version> + </properties> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <version>${jsonp-api.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + <version>${jsonp-impl.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.container</groupId> + <artifactId>arquillian-weld-embedded</artifactId> + <version>2.0.1.Final</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jboss.weld.se</groupId> + <artifactId>weld-se</artifactId> + <version>2.4.3.Final</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project>
diff --git a/impl-tck/tck-tests-plugability/pom.xml b/impl-tck/tck-tests-plugability/pom.xml new file mode 100644 index 0000000..c3e035d --- /dev/null +++ b/impl-tck/tck-tests-plugability/pom.xml
@@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json-tck</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>jakarta.json-tck-tests-plugability</artifactId> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck-tests-plugability</artifactId> + <version>${jsonp-tck.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck-common</artifactId> + <version>${jsonp-tck.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.0.0-M4</version> + <configuration> + <dependenciesToScan> + <dependency>jakarta.json:jakarta.json-tck-tests-plugability</dependency> + </dependenciesToScan> + <trimStackTrace>false</trimStackTrace> + <failIfNoTests>true</failIfNoTests> + </configuration> + </plugin> + </plugins> + </build> +</project>
diff --git a/impl-tck/tck-tests/pom.xml b/impl-tck/tck-tests/pom.xml new file mode 100644 index 0000000..006e732 --- /dev/null +++ b/impl-tck/tck-tests/pom.xml
@@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json-tck</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>jakarta.json-tck-tests</artifactId> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck-tests</artifactId> + <version>${jsonp-tck.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck-common</artifactId> + <version>${jsonp-tck.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.0.0-M4</version> + <configuration> + <dependenciesToScan> + <dependency>jakarta.json:jakarta.json-tck-tests</dependency> + </dependenciesToScan> + <trimStackTrace>false</trimStackTrace> + <failIfNoTests>true</failIfNoTests> + </configuration> + </plugin> + </plugins> + </build> +</project>
diff --git a/impl/pom.xml b/impl/pom.xml new file mode 100644 index 0000000..3bfd523 --- /dev/null +++ b/impl/pom.xml
@@ -0,0 +1,248 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish</groupId> + <artifactId>json</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + <packaging>bundle</packaging> + <version>2.0.1</version> + <name>JSON-P Default Provider</name> + <description>Default provider for Jakarta JSON Processing</description> + <url>https://github.com/eclipse-ee4j/jsonp</url> + + <properties> + <packages.private>org.glassfish.json</packages.private> + <packages.export>jakarta.json.*,org.glassfish.json.api</packages.export> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.glassfish.build</groupId> + <artifactId>spec-version-maven-plugin</artifactId> + <configuration> + <spec> + <nonFinal>${non.final}</nonFinal> + <jarType>impl</jarType> + <specVersion>${spec_version}</specVersion> + <newSpecVersion>${new_spec_version}</newSpecVersion> + <specImplVersion>${new_spec_impl_version}</specImplVersion> + <implVersion>${impl_version}</implVersion> + <newImplVersion>${new_impl_version}</newImplVersion> + <apiPackage>${api_package}</apiPackage> + <implNamespace>${impl_namespace}</implNamespace> + </spec> + </configuration> + <executions> + <execution> + <goals> + <goal>set-spec-properties</goal> + <!-- TODO: + glassfish-spec-version-maven-plugin needs to be updated + in order to check 'jakarta.' prefixed values in manifest entries + --> + <!--<goal>check-module</goal>--> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <configuration> + <skipSource>true</skipSource> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>sources-as-resources</id> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <resources> + <resource> + <directory>src/main/java/org</directory> + </resource> + </resources> + <outputDirectory>${project.build.directory}/sources/org</outputDirectory> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>unpack-module-info</id> + <phase>compile</phase> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <configuration> + <includeArtifactIds>jakarta.json-api</includeArtifactIds> + <outputDirectory>${project.build.directory}/binaries</outputDirectory> + <includes>module-info.class</includes> + </configuration> + </execution> + <execution> + <id>unpack-client-sources</id> + <phase>prepare-package</phase> + <goals> + <goal>unpack</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <version>${jakarta.json-api.version}</version> + <classifier>sources</classifier> + <overWrite>false</overWrite> + <outputDirectory>${project.build.directory}/sources</outputDirectory> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <id>attach-source-jar</id> + <goals> + <goal>jar</goal> + </goals> + <configuration> + <classifier>sources</classifier> + <classesDirectory>${project.build.directory}/sources</classesDirectory> + </configuration> + </execution> + </executions> + </plugin> + <!-- + This plugin is reponsible for packaging artifacts + as OSGi bundles. Please refer to + http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html + for more information about how to use this plugin. + --> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <executions> + <execution> + <id>default-bundle</id> + <goals> + <goal>bundle</goal> + </goals> + <configuration> + <instructions> + <Bundle-Version>${spec.bundle.version}</Bundle-Version> + <Bundle-SymbolicName>${spec.bundle.symbolic-name}</Bundle-SymbolicName> + <Extension-Name>${spec.extension.name}</Extension-Name> + <Implementation-Version>${spec.implementation.version}</Implementation-Version> + <Specification-Vendor>Eclipse Foundation</Specification-Vendor> + <Specification-Version>${spec.specification.version}</Specification-Version> + <Export-Package>${packages.export}</Export-Package> + <Private-Package>${packages.private}</Private-Package> + <_donotcopy>.*services.*</_donotcopy> + <!-- as of 5.1.1 this won't add appropriate uses jakarta.json.spi.JsonProvider; to module-info --> + <!--<_jpms-module-info>jakarta.json</_jpms-module-info>--> + <Include-Resource>{maven-resources},target/binaries/module-info.class</Include-Resource> + </instructions> + </configuration> + </execution> + <execution> + <id>main-artifact-module</id> + <goals> + <goal>bundle</goal> + </goals> + <configuration> + <classifier>module</classifier> + <instructions> + <Bundle-Version>${spec.bundle.version}</Bundle-Version> + <Bundle-SymbolicName>${spec.bundle.symbolic-name}.module</Bundle-SymbolicName> + <Extension-Name>${spec.extension.name}</Extension-Name> + <Implementation-Version>${spec.implementation.version}</Implementation-Version> + <Specification-Version>${spec.specification.version}</Specification-Version> + <Export-Package>org.glassfish.json.api</Export-Package> + <Private-Package>${packages.private}</Private-Package> + <Include-Resource>{maven-resources},target/classes/module-info.class</Include-Resource> + </instructions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <configuration> + <sourcepath>target/sources</sourcepath> + <archive> + <manifest> + <addDefaultEntries>false</addDefaultEntries> + </manifest> + </archive> + <release>11</release> + <notimestamp>true</notimestamp> + <docfilessubdirs>true</docfilessubdirs> + <description>JSON Processing API documentation</description> + <doctitle>JSON Processing API documentation</doctitle> + <windowtitle>JSON Processing API documentation</windowtitle> + <header><![CDATA[<br>JSON Processing API v${project.version}]]></header> + <bottom><![CDATA[ +Comments to: <a href="mailto:jsonp-dev@eclipse.org">jsonp-dev@eclipse.org</a>.<br> +Copyright © 2019, 2020 Eclipse Foundation. All rights reserved.<br> +Use is subject to <a href="{@docRoot}/doc-files/speclicense.html" target="_top">license terms</a>.]]> + </bottom> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + +</project>
diff --git a/impl/src/main/java/module-info.java b/impl/src/main/java/module-info.java new file mode 100644 index 0000000..53be057 --- /dev/null +++ b/impl/src/main/java/module-info.java
@@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +module org.glassfish.jakarta.json { + requires transitive jakarta.json; + exports org.glassfish.json.api; + provides jakarta.json.spi.JsonProvider with org.glassfish.json.JsonProviderImpl; +}
diff --git a/impl/src/main/java/org/glassfish/json/BufferPoolImpl.java b/impl/src/main/java/org/glassfish/json/BufferPoolImpl.java new file mode 100644 index 0000000..460c6f7 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/BufferPoolImpl.java
@@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import java.lang.ref.WeakReference; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * char[] pool that pool instances of char[] which are expensive to create. + * + * @author Jitendra Kotamraju + */ +class BufferPoolImpl implements BufferPool { + + // volatile since multiple threads may access queue reference + private volatile WeakReference<ConcurrentLinkedQueue<char[]>> queue; + + /** + * Gets a new object from the pool. + * + * <p> + * If no object is available in the pool, this method creates a new one. + * + * @return + * always non-null. + */ + @Override + public final char[] take() { + char[] t = getQueue().poll(); + if (t==null) + return new char[4096]; + return t; + } + + private ConcurrentLinkedQueue<char[]> getQueue() { + WeakReference<ConcurrentLinkedQueue<char[]>> q = queue; + if (q != null) { + ConcurrentLinkedQueue<char[]> d = q.get(); + if (d != null) + return d; + } + + // overwrite the queue + ConcurrentLinkedQueue<char[]> d = new ConcurrentLinkedQueue<>(); + queue = new WeakReference<>(d); + + return d; + } + + /** + * Returns an object back to the pool. + */ + @Override + public final void recycle(char[] t) { + getQueue().offer(t); + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonArrayBuilderImpl.java b/impl/src/main/java/org/glassfish/json/JsonArrayBuilderImpl.java new file mode 100644 index 0000000..b0c3085 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonArrayBuilderImpl.java
@@ -0,0 +1,488 @@ +/* + * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.*; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * JsonArrayBuilder implementation + * + * @author Jitendra Kotamraju + * @author Kin-man Chung + */ + +class JsonArrayBuilderImpl implements JsonArrayBuilder { + private ArrayList<JsonValue> valueList; + private final BufferPool bufferPool; + + JsonArrayBuilderImpl(BufferPool bufferPool) { + this.bufferPool = bufferPool; + } + + JsonArrayBuilderImpl(JsonArray array, BufferPool bufferPool) { + this.bufferPool = bufferPool; + valueList = new ArrayList<>(); + valueList.addAll(array); + } + + JsonArrayBuilderImpl(Collection<?> collection, BufferPool bufferPool) { + this.bufferPool = bufferPool; + valueList = new ArrayList<>(); + populate(collection); + } + + @Override + public JsonArrayBuilder add(JsonValue value) { + validateValue(value); + addValueList(value); + return this; + } + + @Override + public JsonArrayBuilder add(String value) { + validateValue(value); + addValueList(new JsonStringImpl(value)); + return this; + } + + @Override + public JsonArrayBuilder add(BigDecimal value) { + validateValue(value); + addValueList(JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(BigInteger value) { + validateValue(value); + addValueList(JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(int value) { + addValueList(JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(long value) { + addValueList(JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(double value) { + addValueList(JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(boolean value) { + addValueList(value ? JsonValue.TRUE : JsonValue.FALSE); + return this; + } + + @Override + public JsonArrayBuilder addNull() { + addValueList(JsonValue.NULL); + return this; + } + + @Override + public JsonArrayBuilder add(JsonObjectBuilder builder) { + if (builder == null) { + throw new NullPointerException(JsonMessages.ARRBUILDER_OBJECT_BUILDER_NULL()); + } + addValueList(builder.build()); + return this; + } + + @Override + public JsonArrayBuilder add(JsonArrayBuilder builder) { + if (builder == null) { + throw new NullPointerException(JsonMessages.ARRBUILDER_ARRAY_BUILDER_NULL()); + } + addValueList(builder.build()); + return this; + } + + @Override + public JsonArrayBuilder addAll(JsonArrayBuilder builder) { + if (builder == null) { + throw new NullPointerException(JsonMessages.ARRBUILDER_ARRAY_BUILDER_NULL()); + } + if (valueList == null) { + valueList = new ArrayList<>(); + } + valueList.addAll(builder.build()); + return this; + } + + @Override + public JsonArrayBuilder add(int index, JsonValue value) { + validateValue(value); + addValueList(index, value); + return this; + } + + @Override + public JsonArrayBuilder add(int index, String value) { + validateValue(value); + addValueList(index, new JsonStringImpl(value)); + return this; + } + + @Override + public JsonArrayBuilder add(int index, BigDecimal value) { + validateValue(value); + addValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(int index, BigInteger value) { + validateValue(value); + addValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(int index, int value) { + addValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(int index, long value) { + addValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(int index, double value) { + addValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder add(int index, boolean value) { + addValueList(index, value ? JsonValue.TRUE : JsonValue.FALSE); + return this; + } + + @Override + public JsonArrayBuilder addNull(int index) { + addValueList(index, JsonValue.NULL); + return this; + } + + @Override + public JsonArrayBuilder add(int index, JsonObjectBuilder builder) { + if (builder == null) { + throw new NullPointerException(JsonMessages.ARRBUILDER_OBJECT_BUILDER_NULL()); + } + addValueList(index, builder.build()); + return this; + } + + @Override + public JsonArrayBuilder add(int index, JsonArrayBuilder builder) { + if (builder == null) { + throw new NullPointerException(JsonMessages.ARRBUILDER_OBJECT_BUILDER_NULL()); + } + addValueList(index, builder.build()); + return this; + } + + @Override + public JsonArrayBuilder set(int index, JsonValue value) { + validateValue(value); + setValueList(index, value); + return this; + } + + @Override + public JsonArrayBuilder set(int index, String value) { + validateValue(value); + setValueList(index, new JsonStringImpl(value)); + return this; + } + + @Override + public JsonArrayBuilder set(int index, BigDecimal value) { + validateValue(value); + setValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder set(int index, BigInteger value) { + validateValue(value); + setValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder set(int index, int value) { + setValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder set(int index, long value) { + setValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder set(int index, double value) { + setValueList(index, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonArrayBuilder set(int index, boolean value) { + setValueList(index, value ? JsonValue.TRUE : JsonValue.FALSE); + return this; + } + + @Override + public JsonArrayBuilder setNull(int index) { + setValueList(index, JsonValue.NULL); + return this; + } + + @Override + public JsonArrayBuilder set(int index, JsonObjectBuilder builder) { + if (builder == null) { + throw new NullPointerException(JsonMessages.ARRBUILDER_OBJECT_BUILDER_NULL()); + } + setValueList(index, builder.build()); + return this; + } + + @Override + public JsonArrayBuilder set(int index, JsonArrayBuilder builder) { + if (builder == null) { + throw new NullPointerException(JsonMessages.ARRBUILDER_OBJECT_BUILDER_NULL()); + } + setValueList(index, builder.build()); + return this; + } + + @Override + public JsonArrayBuilder remove(int index) { + if (valueList == null) { + throw new IndexOutOfBoundsException(JsonMessages.ARRBUILDER_VALUELIST_NULL(index, 0)); + } + valueList.remove(index); + return this; + } + + @Override + public JsonArray build() { + List<JsonValue> snapshot; + if (valueList == null) { + snapshot = Collections.emptyList(); + } else { + // Should we trim to minimize storage ? + // valueList.trimToSize(); + snapshot = Collections.unmodifiableList(valueList); + } + valueList = null; + return new JsonArrayImpl(snapshot, bufferPool); + } + + private void populate(Collection<?> collection) { + for (Object value : collection) { + if (value != null && value instanceof Optional) { + ((Optional<?>) value).ifPresent(v -> + this.valueList.add(MapUtil.handle(v, bufferPool))); + } else { + this.valueList.add(MapUtil.handle(value, bufferPool)); + } + } + } + + private void addValueList(JsonValue value) { + if (valueList == null) { + valueList = new ArrayList<>(); + } + valueList.add(value); + } + + private void addValueList(int index, JsonValue value) { + if (valueList == null) { + valueList = new ArrayList<>(); + } + valueList.add(index, value); + } + + private void setValueList(int index, JsonValue value) { + if (valueList == null) { + throw new IndexOutOfBoundsException(JsonMessages.ARRBUILDER_VALUELIST_NULL(index, 0)); + } + valueList.set(index, value); + } + + private void validateValue(Object value) { + if (value == null) { + throw new NullPointerException(JsonMessages.ARRBUILDER_VALUE_NULL()); + } + } + + private static final class JsonArrayImpl extends AbstractList<JsonValue> implements JsonArray { + private final List<JsonValue> valueList; // Unmodifiable + private final BufferPool bufferPool; + private int hashCode; + + JsonArrayImpl(List<JsonValue> valueList, BufferPool bufferPool) { + this.valueList = valueList; + this.bufferPool = bufferPool; + } + + @Override + public int size() { + return valueList.size(); + } + + @Override + public JsonObject getJsonObject(int index) { + return (JsonObject)valueList.get(index); + } + + @Override + public JsonArray getJsonArray(int index) { + return (JsonArray)valueList.get(index); + } + + @Override + public JsonNumber getJsonNumber(int index) { + return (JsonNumber)valueList.get(index); + } + + @Override + public JsonString getJsonString(int index) { + return (JsonString)valueList.get(index); + } + + @Override + @SuppressWarnings("unchecked") + public <T extends JsonValue> List<T> getValuesAs(Class<T> clazz) { + return (List<T>)valueList; + } + + @Override + public String getString(int index) { + return getJsonString(index).getString(); + } + + @Override + public String getString(int index, String defaultValue) { + try { + return getString(index); + } catch (Exception e) { + return defaultValue; + } + } + + @Override + public int getInt(int index) { + return getJsonNumber(index).intValue(); + } + + @Override + public int getInt(int index, int defaultValue) { + try { + return getInt(index); + } catch (Exception e) { + return defaultValue; + } + } + + @Override + public boolean getBoolean(int index) { + JsonValue jsonValue = get(index); + if (jsonValue == JsonValue.TRUE) { + return true; + } else if (jsonValue == JsonValue.FALSE) { + return false; + } else { + throw new ClassCastException(); + } + } + + @Override + public boolean getBoolean(int index, boolean defaultValue) { + try { + return getBoolean(index); + } catch (Exception e) { + return defaultValue; + } + } + + @Override + public boolean isNull(int index) { + return valueList.get(index).equals(JsonValue.NULL); + } + + @Override + public ValueType getValueType() { + return ValueType.ARRAY; + } + + @Override + public JsonValue get(int index) { + return valueList.get(index); + } + + @Override + public int hashCode() { + if (hashCode == 0) { + hashCode = super.hashCode(); + } + return hashCode; + } + + @Override + public String toString() { + StringWriter sw = new StringWriter(); + try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool)) { + jw.write(this); + } + return sw.toString(); + } + + @Override + public JsonArray asJsonArray() { + return this; + } + } +} +
diff --git a/impl/src/main/java/org/glassfish/json/JsonBuilderFactoryImpl.java b/impl/src/main/java/org/glassfish/json/JsonBuilderFactoryImpl.java new file mode 100644 index 0000000..7fde7a3 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonBuilderFactoryImpl.java
@@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import java.util.Collection; +import org.glassfish.json.api.BufferPool; + +import jakarta.json.JsonObject; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObjectBuilder; +import java.util.Collections; +import java.util.Map; + +/** + * @author Jitendra Kotamraju + */ +class JsonBuilderFactoryImpl implements JsonBuilderFactory { + private final Map<String, ?> config; + private final BufferPool bufferPool; + private final boolean rejectDuplicateKeys; + + JsonBuilderFactoryImpl(BufferPool bufferPool, boolean rejectDuplicateKeys) { + this.config = Collections.emptyMap(); + this.bufferPool = bufferPool; + this.rejectDuplicateKeys = rejectDuplicateKeys; + } + + @Override + public JsonObjectBuilder createObjectBuilder() { + return new JsonObjectBuilderImpl(bufferPool, rejectDuplicateKeys); + } + + @Override + public JsonObjectBuilder createObjectBuilder(JsonObject object) { + return new JsonObjectBuilderImpl(object, bufferPool, rejectDuplicateKeys); + } + + @Override + public JsonObjectBuilder createObjectBuilder(Map<String, Object> object) { + return new JsonObjectBuilderImpl(object, bufferPool, rejectDuplicateKeys); + } + + @Override + public JsonArrayBuilder createArrayBuilder() { + return new JsonArrayBuilderImpl(bufferPool); + } + + @Override + public JsonArrayBuilder createArrayBuilder(JsonArray array) { + return new JsonArrayBuilderImpl(array, bufferPool); + } + + @Override + public JsonArrayBuilder createArrayBuilder(Collection<?> collection) { + return new JsonArrayBuilderImpl(collection, bufferPool); + } + + @Override + public Map<String, ?> getConfigInUse() { + return config; + } +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonGeneratorFactoryImpl.java b/impl/src/main/java/org/glassfish/json/JsonGeneratorFactoryImpl.java new file mode 100644 index 0000000..e347641 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonGeneratorFactoryImpl.java
@@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonGeneratorFactory; +import java.io.OutputStream; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.Map; + +/** + * @author Jitendra Kotamraju + */ +class JsonGeneratorFactoryImpl implements JsonGeneratorFactory { + + private final boolean prettyPrinting; + private final Map<String, ?> config; // unmodifiable map + private final BufferPool bufferPool; + + JsonGeneratorFactoryImpl(Map<String, ?> config, boolean prettyPrinting, + BufferPool bufferPool) { + this.config = config; + this.prettyPrinting = prettyPrinting; + this.bufferPool = bufferPool; + } + + @Override + public JsonGenerator createGenerator(Writer writer) { + return prettyPrinting + ? new JsonPrettyGeneratorImpl(writer, bufferPool) + : new JsonGeneratorImpl(writer, bufferPool); + } + + @Override + public JsonGenerator createGenerator(OutputStream out) { + return prettyPrinting + ? new JsonPrettyGeneratorImpl(out, bufferPool) + : new JsonGeneratorImpl(out, bufferPool); + } + + @Override + public JsonGenerator createGenerator(OutputStream out, Charset charset) { + return prettyPrinting + ? new JsonPrettyGeneratorImpl(out, charset, bufferPool) + : new JsonGeneratorImpl(out, charset, bufferPool); + } + + @Override + public Map<String, ?> getConfigInUse() { + return config; + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonGeneratorImpl.java b/impl/src/main/java/org/glassfish/json/JsonGeneratorImpl.java new file mode 100644 index 0000000..67c8e33 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonGeneratorImpl.java
@@ -0,0 +1,715 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.*; +import jakarta.json.stream.JsonGenerationException; +import jakarta.json.stream.JsonGenerator; +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Map; + +/** + * @author Jitendra Kotamraju + */ +class JsonGeneratorImpl implements JsonGenerator { + + private static final char[] INT_MIN_VALUE_CHARS = "-2147483648".toCharArray(); + private static final int[] INT_CHARS_SIZE_TABLE = { 9, 99, 999, 9999, 99999, + 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE }; + + private static final char [] DIGIT_TENS = { + '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', + '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', + '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', + '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', + '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', + '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', + '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', + '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', + '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', + '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', + } ; + + private static final char [] DIGIT_ONES = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + } ; + + /** + * All possible chars for representing a number as a String + */ + private static final char[] DIGITS = { + '0' , '1' , '2' , '3' , '4' , '5' , + '6' , '7' , '8' , '9' + }; + + private static enum Scope { + IN_NONE, + IN_OBJECT, + IN_FIELD, + IN_ARRAY + } + + private final BufferPool bufferPool; + private final Writer writer; + private Context currentContext = new Context(Scope.IN_NONE); + private final Deque<Context> stack = new ArrayDeque<>(); + + // Using own buffering mechanism as JDK's BufferedWriter uses synchronized + // methods. Also, flushBuffer() is useful when you don't want to actually + // flush the underlying output source + private final char buf[]; // capacity >= INT_MIN_VALUE_CHARS.length + private int len = 0; + + JsonGeneratorImpl(Writer writer, BufferPool bufferPool) { + this.writer = writer; + this.bufferPool = bufferPool; + this.buf = bufferPool.take(); + } + + JsonGeneratorImpl(OutputStream out, BufferPool bufferPool) { + this(out, StandardCharsets.UTF_8, bufferPool); + } + + JsonGeneratorImpl(OutputStream out, Charset encoding, BufferPool bufferPool) { + this(new OutputStreamWriter(out, encoding), bufferPool); + } + + @Override + public void flush() { + flushBuffer(); + try { + writer.flush(); + } catch (IOException ioe) { + throw new JsonException(JsonMessages.GENERATOR_FLUSH_IO_ERR(), ioe); + } + } + + @Override + public JsonGenerator writeStartObject() { + if (currentContext.scope == Scope.IN_OBJECT) { + throw new JsonGenerationException(JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + if (currentContext.scope == Scope.IN_NONE && !currentContext.first) { + throw new JsonGenerationException(JsonMessages.GENERATOR_ILLEGAL_MULTIPLE_TEXT()); + } + writeComma(); + writeChar('{'); + stack.push(currentContext); + currentContext = new Context(Scope.IN_OBJECT); + return this; + } + + @Override + public JsonGenerator writeStartObject(String name) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + writeChar('{'); + stack.push(currentContext); + currentContext = new Context(Scope.IN_OBJECT); + return this; + } + + private JsonGenerator writeName(String name) { + writeComma(); + writeEscapedString(name); + writeColon(); + return this; + } + + @Override + public JsonGenerator write(String name, String fieldValue) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + writeEscapedString(fieldValue); + return this; + } + + @Override + public JsonGenerator write(String name, int value) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + writeInt(value); + return this; + } + + @Override + public JsonGenerator write(String name, long value) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + writeString(String.valueOf(value)); + return this; + } + + @Override + public JsonGenerator write(String name, double value) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + if (Double.isInfinite(value) || Double.isNaN(value)) { + throw new NumberFormatException(JsonMessages.GENERATOR_DOUBLE_INFINITE_NAN()); + } + writeName(name); + writeString(String.valueOf(value)); + return this; + } + + @Override + public JsonGenerator write(String name, BigInteger value) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + writeString(String.valueOf(value)); + return this; + } + + @Override + public JsonGenerator write(String name, BigDecimal value) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + writeString(String.valueOf(value)); + return this; + } + + @Override + public JsonGenerator write(String name, boolean value) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + writeString(value? "true" : "false"); + return this; + } + + @Override + public JsonGenerator writeNull(String name) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + writeString("null"); + return this; + } + + @Override + public JsonGenerator write(JsonValue value) { + checkContextForValue(); + + switch (value.getValueType()) { + case ARRAY: + JsonArray array = (JsonArray)value; + writeStartArray(); + for(JsonValue child: array) { + write(child); + } + writeEnd(); + break; + case OBJECT: + JsonObject object = (JsonObject)value; + writeStartObject(); + for(Map.Entry<String, JsonValue> member: object.entrySet()) { + write(member.getKey(), member.getValue()); + } + writeEnd(); + break; + case STRING: + JsonString str = (JsonString)value; + write(str.getString()); + break; + case NUMBER: + JsonNumber number = (JsonNumber)value; + writeValue(number.toString()); + popFieldContext(); + break; + case TRUE: + write(true); + break; + case FALSE: + write(false); + break; + case NULL: + writeNull(); + break; + } + + return this; + } + + @Override + public JsonGenerator writeStartArray() { + if (currentContext.scope == Scope.IN_OBJECT) { + throw new JsonGenerationException(JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + if (currentContext.scope == Scope.IN_NONE && !currentContext.first) { + throw new JsonGenerationException(JsonMessages.GENERATOR_ILLEGAL_MULTIPLE_TEXT()); + } + writeComma(); + writeChar('['); + stack.push(currentContext); + currentContext = new Context(Scope.IN_ARRAY); + return this; + } + + @Override + public JsonGenerator writeStartArray(String name) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + writeChar('['); + stack.push(currentContext); + currentContext = new Context(Scope.IN_ARRAY); + return this; + } + + @Override + public JsonGenerator write(String name, JsonValue value) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + switch (value.getValueType()) { + case ARRAY: + JsonArray array = (JsonArray)value; + writeStartArray(name); + for(JsonValue child: array) { + write(child); + } + writeEnd(); + break; + case OBJECT: + JsonObject object = (JsonObject)value; + writeStartObject(name); + for(Map.Entry<String, JsonValue> member: object.entrySet()) { + write(member.getKey(), member.getValue()); + } + writeEnd(); + break; + case STRING: + JsonString str = (JsonString)value; + write(name, str.getString()); + break; + case NUMBER: + JsonNumber number = (JsonNumber)value; + writeValue(name, number.toString()); + break; + case TRUE: + write(name, true); + break; + case FALSE: + write(name, false); + break; + case NULL: + writeNull(name); + break; + } + return this; + } + + @Override + public JsonGenerator write(String value) { + checkContextForValue(); + writeComma(); + writeEscapedString(value); + popFieldContext(); + return this; + } + + + @Override + public JsonGenerator write(int value) { + checkContextForValue(); + writeComma(); + writeInt(value); + popFieldContext(); + return this; + } + + @Override + public JsonGenerator write(long value) { + checkContextForValue(); + writeValue(String.valueOf(value)); + popFieldContext(); + return this; + } + + @Override + public JsonGenerator write(double value) { + checkContextForValue(); + if (Double.isInfinite(value) || Double.isNaN(value)) { + throw new NumberFormatException(JsonMessages.GENERATOR_DOUBLE_INFINITE_NAN()); + } + writeValue(String.valueOf(value)); + popFieldContext(); + return this; + } + + @Override + public JsonGenerator write(BigInteger value) { + checkContextForValue(); + writeValue(value.toString()); + popFieldContext(); + return this; + } + + private void checkContextForValue() { + if ((!currentContext.first && currentContext.scope != Scope.IN_ARRAY && currentContext.scope != Scope.IN_FIELD) + || (currentContext.first && currentContext.scope == Scope.IN_OBJECT)) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + } + + @Override + public JsonGenerator write(BigDecimal value) { + checkContextForValue(); + writeValue(value.toString()); + popFieldContext(); + + return this; + } + + private void popFieldContext() { + if (currentContext.scope == Scope.IN_FIELD) { + currentContext = stack.pop(); + } + } + + @Override + public JsonGenerator write(boolean value) { + checkContextForValue(); + writeComma(); + writeString(value ? "true" : "false"); + popFieldContext(); + return this; + } + + @Override + public JsonGenerator writeNull() { + checkContextForValue(); + writeComma(); + writeString("null"); + popFieldContext(); + return this; + } + + private void writeValue(String value) { + writeComma(); + writeString(value); + } + + private void writeValue(String name, String value) { + writeComma(); + writeEscapedString(name); + writeColon(); + writeString(value); + } + + @Override + public JsonGenerator writeKey(String name) { + if (currentContext.scope != Scope.IN_OBJECT) { + throw new JsonGenerationException( + JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope)); + } + writeName(name); + stack.push(currentContext); + currentContext = new Context(Scope.IN_FIELD); + currentContext.first = false; + return this; + } + + @Override + public JsonGenerator writeEnd() { + if (currentContext.scope == Scope.IN_NONE) { + throw new JsonGenerationException("writeEnd() cannot be called in no context"); + } + writeChar(currentContext.scope == Scope.IN_ARRAY ? ']' : '}'); + currentContext = stack.pop(); + popFieldContext(); + return this; + } + + protected void writeComma() { + if (isCommaAllowed()) { + writeChar(','); + } + currentContext.first = false; + } + + protected boolean inNone() { + return currentContext.scope == Scope.IN_NONE; + } + + boolean isCommaAllowed() { + return !currentContext.first && currentContext.scope != Scope.IN_FIELD; + } + + protected void writeColon() { + writeChar(':'); + } + + private static class Context { + boolean first = true; + final Scope scope; + + Context(Scope scope) { + this.scope = scope; + } + + } + + @Override + public void close() { + if (currentContext.scope != Scope.IN_NONE || currentContext.first) { + throw new JsonGenerationException(JsonMessages.GENERATOR_INCOMPLETE_JSON()); + } + flushBuffer(); + try { + writer.close(); + } catch (IOException ioe) { + throw new JsonException(JsonMessages.GENERATOR_CLOSE_IO_ERR(), ioe); + } + bufferPool.recycle(buf); + } + + // begin, end-1 indexes represent characters that need not + // be escaped + // + // XXXssssssssssssXXXXXXXXXXXXXXXXXXXXXXrrrrrrrrrrrrrrXXXXXX + // ^ ^ ^ ^ + // | | | | + // begin end begin end + void writeEscapedString(String string) { + writeChar('"'); + int len = string.length(); + for(int i = 0; i < len; i++) { + int begin = i, end = i; + char c = string.charAt(i); + // find all the characters that need not be escaped + // unescaped = %x20-21 | %x23-5B | %x5D-10FFFF + while(c >= 0x20 && c <= 0x10ffff && c != 0x22 && c != 0x5c) { + i++; end = i; + if (i < len) { + c = string.charAt(i); + } else { + break; + } + } + // Write characters without escaping + if (begin < end) { + writeString(string, begin, end); + if (i == len) { + break; + } + } + + switch (c) { + case '"': + case '\\': + writeChar('\\'); writeChar(c); + break; + case '\b': + writeChar('\\'); writeChar('b'); + break; + case '\f': + writeChar('\\'); writeChar('f'); + break; + case '\n': + writeChar('\\'); writeChar('n'); + break; + case '\r': + writeChar('\\'); writeChar('r'); + break; + case '\t': + writeChar('\\'); writeChar('t'); + break; + default: + String hex = "000" + Integer.toHexString(c); + writeString("\\u" + hex.substring(hex.length() - 4)); + } + } + writeChar('"'); + } + + void writeString(String str, int begin, int end) { + while (begin < end) { // source begin and end indexes + int no = Math.min(buf.length - len, end - begin); + str.getChars(begin, begin + no, buf, len); + begin += no; // Increment source index + len += no; // Increment dest index + if (len >= buf.length) { + flushBuffer(); + } + } + } + + void writeString(String str) { + writeString(str, 0, str.length()); + } + + void writeChar(char c) { + if (len >= buf.length) { + flushBuffer(); + } + buf[len++] = c; + } + + // Not using Integer.toString() since it creates intermediary String + // Also, we want the chars to be copied to our buffer directly + void writeInt(int num) { + int size; + if (num == Integer.MIN_VALUE) { + size = INT_MIN_VALUE_CHARS.length; + } else { + size = (num < 0) ? stringSize(-num) + 1 : stringSize(num); + } + if (len+size >= buf.length) { + flushBuffer(); + } + if (num == Integer.MIN_VALUE) { + System.arraycopy(INT_MIN_VALUE_CHARS, 0, buf, len, size); + } else { + fillIntChars(num, buf, len+size); + } + len += size; + } + + // flushBuffer writes the buffered contents to writer. But incase of + // byte stream, an OuputStreamWriter is created and that buffers too. + // We may need to call OutputStreamWriter#flushBuffer() using + // reflection if that is really required (commented out below) + void flushBuffer() { + try { + if (len > 0) { + writer.write(buf, 0, len); + len = 0; + } + } catch (IOException ioe) { + throw new JsonException(JsonMessages.GENERATOR_WRITE_IO_ERR(), ioe); + } + } + +// private static final Method flushBufferMethod; +// static { +// Method m = null; +// try { +// m = OutputStreamWriter.class.getDeclaredMethod("flushBuffer"); +// m.setAccessible(true); +// } catch (Exception e) { +// // no-op +// } +// flushBufferMethod = m; +// } +// void flushBufferOSW() { +// flushBuffer(); +// if (writer instanceof OutputStreamWriter) { +// try { +// flushBufferMethod.invoke(writer); +// } catch (Exception e) { +// // no-op +// } +// } +// } + + // Requires positive x + private static int stringSize(int x) { + for (int i=0; ; i++) + if (x <= INT_CHARS_SIZE_TABLE[i]) + return i+1; + } + + /** + * Places characters representing the integer i into the + * character array buf. The characters are placed into + * the buffer backwards starting with the least significant + * digit at the specified index (exclusive), and working + * backwards from there. + * + * Will fail if i == Integer.MIN_VALUE + */ + private static void fillIntChars(int i, char[] buf, int index) { + int q, r; + int charPos = index; + char sign = 0; + + if (i < 0) { + sign = '-'; + i = -i; + } + + // Generate two digits per iteration + while (i >= 65536) { + q = i / 100; + // really: r = i - (q * 100); + r = i - ((q << 6) + (q << 5) + (q << 2)); + i = q; + buf [--charPos] = DIGIT_ONES[r]; + buf [--charPos] = DIGIT_TENS[r]; + } + + // Fall thru to fast mode for smaller numbers + // assert(i <= 65536, i); + for (;;) { + q = (i * 52429) >>> (16+3); + r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... + buf [--charPos] = DIGITS[r]; + i = q; + if (i == 0) break; + } + if (sign != 0) { + buf [--charPos] = sign; + } + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonLocationImpl.java b/impl/src/main/java/org/glassfish/json/JsonLocationImpl.java new file mode 100644 index 0000000..f5ff424 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonLocationImpl.java
@@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.stream.JsonLocation; + +/** + * @author Jitendra Kotamraju + */ +class JsonLocationImpl implements JsonLocation { + static final JsonLocation UNKNOWN = new JsonLocationImpl(-1, -1, -1); + + private final long columnNo; + private final long lineNo; + private final long offset; + + JsonLocationImpl(long lineNo, long columnNo, long streamOffset) { + this.lineNo = lineNo; + this.columnNo = columnNo; + this.offset = streamOffset; + } + + @Override + public long getLineNumber() { + return lineNo; + } + + @Override + public long getColumnNumber() { + return columnNo; + } + + @Override + public long getStreamOffset() { + return offset; + } + + @Override + public String toString() { + return "(line no="+lineNo+", column no="+columnNo+", offset="+ offset +")"; + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonMergePatchImpl.java b/impl/src/main/java/org/glassfish/json/JsonMergePatchImpl.java new file mode 100644 index 0000000..1a1a2e7 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonMergePatchImpl.java
@@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.JsonMergePatch; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; + +/** + * This class is an implementation of a JSON Merge Patch as specified in + * <a href="http://tools.ietf.org/html/rfc7396">RFC 7396</a>. + * + * @since 1.1 + */ + +public final class JsonMergePatchImpl implements JsonMergePatch { + + private JsonValue patch; + + public JsonMergePatchImpl(JsonValue patch) { + this.patch = patch; + } + + @Override + public JsonValue apply(JsonValue target) { + return mergePatch(target, patch); + } + + @Override + public JsonValue toJsonValue() { + return patch; + } + /** + * Applies the specified patch to the specified target. + * The target is not modified by the patch. + * + * @param target the {@code JsonValue} to apply the patch operations + * @param patch the patch + * @return the {@code JsonValue} as the result of applying the patch + * operations on the target. + */ + private static JsonValue mergePatch(JsonValue target, JsonValue patch) { + + if (patch.getValueType() != JsonValue.ValueType.OBJECT) { + return patch; + } + if (target.getValueType() != JsonValue.ValueType.OBJECT) { + target = JsonValue.EMPTY_JSON_OBJECT; + } + JsonObject targetJsonObject = target.asJsonObject(); + JsonObjectBuilder builder = + new JsonObjectBuilderImpl(targetJsonObject, JsonUtil.getInternalBufferPool()); + patch.asJsonObject().forEach((key, value) -> { + if (value == JsonValue.NULL) { + if (targetJsonObject.containsKey(key)) { + builder.remove(key); + } + } else if (targetJsonObject.containsKey(key)) { + builder.add(key, mergePatch(targetJsonObject.get(key), value)); + } else { + builder.add(key, mergePatch(JsonValue.EMPTY_JSON_OBJECT, value)); + } + }); + return builder.build(); + } + + /** + * Generate a JSON Merge Patch from the source and target {@code JsonValue}. + * @param source the source + * @param target the target + * @return a JSON Patch which when applied to the source, yields the target + */ + static JsonValue diff(JsonValue source, JsonValue target) { + if (source.getValueType() != JsonValue.ValueType.OBJECT || + target.getValueType() != JsonValue.ValueType.OBJECT) { + return target; + } + JsonObject s = (JsonObject) source; + JsonObject t = (JsonObject) target; + JsonObjectBuilder builder = new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()); + // First find members to be replaced or removed + s.forEach((key, value) -> { + if (t.containsKey(key)) { + // key present in both. + if (! value.equals(t.get(key))) { + // If the values are equal, nop, else get diff for the values + builder.add(key, diff(value, t.get(key))); + } + } else { + builder.addNull(key); + } + }); + // Then find members to be added + t.forEach((key, value) -> { + if (! s.containsKey(key)) + builder.add(key, value); + }); + return builder.build(); + } + +} +
diff --git a/impl/src/main/java/org/glassfish/json/JsonMessages.java b/impl/src/main/java/org/glassfish/json/JsonMessages.java new file mode 100644 index 0000000..962cdbe --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonMessages.java
@@ -0,0 +1,294 @@ +/* + * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + + +import jakarta.json.stream.JsonLocation; +import jakarta.json.stream.JsonParser; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; + +/** + * Defines string formatting method for each constant in the resource file + * + * @author Jitendra Kotamraju + */ +final class JsonMessages { + private static final ResourceBundle BUNDLE = + ResourceBundle.getBundle("org.glassfish.json.messages"); + + // global/shared messages + static String INTERNAL_ERROR() { + return localize("internal.error"); + } + + // tokenizer messages + static String TOKENIZER_UNEXPECTED_CHAR(int unexpected, JsonLocation location) { + return localize("tokenizer.unexpected.char", unexpected, location); + } + + static String TOKENIZER_EXPECTED_CHAR(int unexpected, JsonLocation location, char expected) { + return localize("tokenizer.expected.char", unexpected, location, expected); + } + + static String TOKENIZER_IO_ERR() { + return localize("tokenizer.io.err"); + } + + + // parser messages + static String PARSER_GETSTRING_ERR(JsonParser.Event event) { + return localize("parser.getString.err", event); + } + + static String PARSER_ISINTEGRALNUMBER_ERR(JsonParser.Event event) { + return localize("parser.isIntegralNumber.err", event); + } + + static String PARSER_GETINT_ERR(JsonParser.Event event) { + return localize("parser.getInt.err", event); + } + + static String PARSER_GETLONG_ERR(JsonParser.Event event) { + return localize("parser.getLong.err", event); + } + + static String PARSER_GETBIGDECIMAL_ERR(JsonParser.Event event) { + return localize("parser.getBigDecimal.err", event); + } + + static String PARSER_GETARRAY_ERR(JsonParser.Event event) { + return localize("parser.getArray.err", event); + } + + static String PARSER_GETOBJECT_ERR(JsonParser.Event event) { + return localize("parser.getObject.err", event); + } + + static String PARSER_GETVALUE_ERR(JsonParser.Event event) { + return localize("parser.getValue.err", event); + } + + static String PARSER_GETVALUESTREAM_ERR() { + return localize("parser.getValueStream.err"); + } + + static String PARSER_EXPECTED_EOF(JsonTokenizer.JsonToken token) { + return localize("parser.expected.eof", token); + } + + static String PARSER_TOKENIZER_CLOSE_IO() { + return localize("parser.tokenizer.close.io"); + } + + static String PARSER_INVALID_TOKEN(JsonTokenizer.JsonToken token, JsonLocation location, String expectedTokens) { + return localize("parser.invalid.token", token, location, expectedTokens); + } + + static String PARSER_STATE_ERR(JsonValue.ValueType type) { + return localize("parser.state.err", type); + } + + static String PARSER_SCOPE_ERR(JsonValue value) { + return localize("parser.scope.err", value); + } + + static String PARSER_INPUT_ENC_DETECT_FAILED() { + return localize("parser.input.enc.detect.failed"); + } + + static String PARSER_INPUT_ENC_DETECT_IOERR() { + return localize("parser.input.enc.detect.ioerr"); + } + + static String DUPLICATE_KEY(String name) { + return localize("parser.duplicate.key", name); + } + + // generator messages + static String GENERATOR_FLUSH_IO_ERR() { + return localize("generator.flush.io.err"); + } + + static String GENERATOR_CLOSE_IO_ERR() { + return localize("generator.close.io.err"); + } + + static String GENERATOR_WRITE_IO_ERR() { + return localize("generator.write.io.err"); + } + + static String GENERATOR_ILLEGAL_METHOD(Object scope) { + return localize("generator.illegal.method", scope); + } + + static String GENERATOR_DOUBLE_INFINITE_NAN() { + return localize("generator.double.infinite.nan"); + } + + static String GENERATOR_INCOMPLETE_JSON() { + return localize("generator.incomplete.json"); + } + + static String GENERATOR_ILLEGAL_MULTIPLE_TEXT() { + return localize("generator.illegal.multiple.text"); + } + + + + // writer messages + static String WRITER_WRITE_ALREADY_CALLED() { + return localize("writer.write.already.called"); + } + + // reader messages + static String READER_READ_ALREADY_CALLED() { + return localize("reader.read.already.called"); + } + + + // obj builder messages + static String OBJBUILDER_NAME_NULL() { + return localize("objbuilder.name.null"); + } + + static String OBJBUILDER_VALUE_NULL() { + return localize("objbuilder.value.null"); + } + + static String OBJBUILDER_OBJECT_BUILDER_NULL() { + return localize("objbuilder.object.builder.null"); + } + + static String OBJBUILDER_ARRAY_BUILDER_NULL() { + return localize("objbuilder.array.builder.null"); + } + + + // array builder messages + static String ARRBUILDER_VALUE_NULL() { + return localize("arrbuilder.value.null"); + } + + static String ARRBUILDER_OBJECT_BUILDER_NULL() { + return localize("arrbuilder.object.builder.null"); + } + + static String ARRBUILDER_ARRAY_BUILDER_NULL() { + return localize("arrbuilder.array.builder.null"); + } + + static String ARRBUILDER_VALUELIST_NULL(int index, int size) { + return localize("arrbuilder.valuelist.null", index, size); + } + + // json pointer messages + static String POINTER_FORMAT_INVALID() { + return localize("pointer.format.invalid"); + } + + static String POINTER_MAPPING_MISSING(JsonObject object, String key) { + return localize("pointer.mapping.missing", object, key); + } + + static String POINTER_REFERENCE_INVALID(JsonValue.ValueType type) { + return localize("pointer.reference.invalid", type.name()); + } + + static String POINTER_ARRAY_INDEX_ERR(String token) { + return localize("pointer.array.index.err", token); + } + + static String POINTER_ARRAY_INDEX_ILLEGAL(String token) { + return localize("pointer.array.index.illegal", token); + } + + // nodereference messages + static String NODEREF_VALUE_ADD_ERR() { + return localize("noderef.value.add.err"); + } + + static String NODEREF_VALUE_CANNOT_REMOVE() { + return localize("noderef.value.cannot.remove"); + } + + static String NODEREF_OBJECT_MISSING(String key) { + return localize("noderef.object.missing", key); + } + + static String NODEREF_ARRAY_INDEX_ERR(int index, int size) { + return localize("noderef.array.index.err", index, size); + } + + // json patch messages + static String PATCH_MUST_BE_ARRAY() { + return localize("patch.must.be.array"); + } + + static String PATCH_MOVE_PROPER_PREFIX(String from, String path) { + return localize("patch.move.proper.prefix", from, path); + } + + static String PATCH_MOVE_TARGET_NULL(String from) { + return localize("patch.move.target.null", from); + } + + static String PATCH_TEST_FAILED(String path, String value) { + return localize("patch.test.failed", path, value); + } + + static String PATCH_ILLEGAL_OPERATION(String operation) { + return localize("patch.illegal.operation", operation); + } + + static String PATCH_MEMBER_MISSING(String operation, String member) { + return localize("patch.member.missing", operation, member); + } + + static String PATCH_OPERATION_MISSING() { + return localize("patch.operation.missing"); + } + + + private static String localize(String key, Object ... args) { + try { + String msg = BUNDLE.getString(key); + return MessageFormat.format(msg, args); + } catch (Exception e) { + return getDefaultMessage(key, args); + } + } + + private static String getDefaultMessage(String key, Object ... args) { + StringBuilder sb = new StringBuilder(); + sb.append("[failed to localize] "); + sb.append(key); + if (args != null) { + sb.append('('); + for (int i = 0; i < args.length; ++i) { + if (i != 0) + sb.append(", "); + sb.append(String.valueOf(args[i])); + } + sb.append(')'); + } + return sb.toString(); + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonNumberImpl.java b/impl/src/main/java/org/glassfish/json/JsonNumberImpl.java new file mode 100644 index 0000000..6678270 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonNumberImpl.java
@@ -0,0 +1,269 @@ +/* + * Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.JsonNumber; +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * JsonNumber impl. Subclasses provide optimized implementations + * when backed by int, long, BigDecimal + * + * @author Jitendra Kotamraju + */ +abstract class JsonNumberImpl implements JsonNumber { + + private int hashCode; + + static JsonNumber getJsonNumber(int num) { + return new JsonIntNumber(num); + } + + static JsonNumber getJsonNumber(long num) { + return new JsonLongNumber(num); + } + + static JsonNumber getJsonNumber(BigInteger value) { + return new JsonBigDecimalNumber(new BigDecimal(value)); + } + + static JsonNumber getJsonNumber(double value) { + //bigDecimal = new BigDecimal(value); + // This is the preferred way to convert double to BigDecimal + return new JsonBigDecimalNumber(BigDecimal.valueOf(value)); + } + + static JsonNumber getJsonNumber(BigDecimal value) { + return new JsonBigDecimalNumber(value); + } + + // Optimized JsonNumber impl for int numbers. + private static final class JsonIntNumber extends JsonNumberImpl { + private final int num; + private BigDecimal bigDecimal; // assigning it lazily on demand + + JsonIntNumber(int num) { + this.num = num; + } + + @Override + public boolean isIntegral() { + return true; + } + + @Override + public int intValue() { + return num; + } + + @Override + public int intValueExact() { + return num; + } + + @Override + public long longValue() { + return num; + } + + @Override + public long longValueExact() { + return num; + } + + @Override + public double doubleValue() { + return num; + } + + @Override + public BigDecimal bigDecimalValue() { + // reference assignments are atomic. At the most some more temp + // BigDecimal objects are created + BigDecimal bd = bigDecimal; + if (bd == null) { + bigDecimal = bd = new BigDecimal(num); + } + return bd; + } + + @Override + public Number numberValue() { + return num; + } + + @Override + public String toString() { + return Integer.toString(num); + } + } + + // Optimized JsonNumber impl for long numbers. + private static final class JsonLongNumber extends JsonNumberImpl { + private final long num; + private BigDecimal bigDecimal; // assigning it lazily on demand + + JsonLongNumber(long num) { + this.num = num; + } + + @Override + public boolean isIntegral() { + return true; + } + + @Override + public int intValue() { + return (int) num; + } + + @Override + public int intValueExact() { + return Math.toIntExact(num); + } + + @Override + public long longValue() { + return num; + } + + @Override + public long longValueExact() { + return num; + } + + @Override + public double doubleValue() { + return num; + } + + @Override + public BigDecimal bigDecimalValue() { + // reference assignments are atomic. At the most some more temp + // BigDecimal objects are created + BigDecimal bd = bigDecimal; + if (bd == null) { + bigDecimal = bd = new BigDecimal(num); + } + return bd; + } + + @Override + public Number numberValue() { + return num; + } + + @Override + public String toString() { + return Long.toString(num); + } + + } + + // JsonNumber impl using BigDecimal numbers. + private static final class JsonBigDecimalNumber extends JsonNumberImpl { + private final BigDecimal bigDecimal; + + JsonBigDecimalNumber(BigDecimal value) { + this.bigDecimal = value; + } + + @Override + public BigDecimal bigDecimalValue() { + return bigDecimal; + } + + @Override + public Number numberValue() { + return bigDecimalValue(); + } + + } + + @Override + public boolean isIntegral() { + return bigDecimalValue().scale() == 0; + } + + @Override + public int intValue() { + return bigDecimalValue().intValue(); + } + + @Override + public int intValueExact() { + return bigDecimalValue().intValueExact(); + } + + @Override + public long longValue() { + return bigDecimalValue().longValue(); + } + + @Override + public long longValueExact() { + return bigDecimalValue().longValueExact(); + } + + @Override + public double doubleValue() { + return bigDecimalValue().doubleValue(); + } + + @Override + public BigInteger bigIntegerValue() { + return bigDecimalValue().toBigInteger(); + } + + @Override + public BigInteger bigIntegerValueExact() { + return bigDecimalValue().toBigIntegerExact(); + } + + @Override + public ValueType getValueType() { + return ValueType.NUMBER; + } + + @Override + public int hashCode() { + if (hashCode == 0) { + hashCode = bigDecimalValue().hashCode(); + } + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if (this == obj){ + return true; + } + if (!(obj instanceof JsonNumber)) { + return false; + } + JsonNumber other = (JsonNumber)obj; + return bigDecimalValue().equals(other.bigDecimalValue()); + } + + @Override + public String toString() { + return bigDecimalValue().toString(); + } + +} +
diff --git a/impl/src/main/java/org/glassfish/json/JsonObjectBuilderImpl.java b/impl/src/main/java/org/glassfish/json/JsonObjectBuilderImpl.java new file mode 100644 index 0000000..1104055 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonObjectBuilderImpl.java
@@ -0,0 +1,366 @@ +/* + * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.*; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; + +/** + * JsonObjectBuilder implementation + * + * @author Jitendra Kotamraju + * @author Kin-man Chung + */ +class JsonObjectBuilderImpl implements JsonObjectBuilder { + + protected Map<String, JsonValue> valueMap; + private final BufferPool bufferPool; + private final boolean rejectDuplicateKeys; + + JsonObjectBuilderImpl(BufferPool bufferPool) { + this.bufferPool = bufferPool; + rejectDuplicateKeys = false; + } + + JsonObjectBuilderImpl(BufferPool bufferPool, boolean rejectDuplicateKeys) { + this.bufferPool = bufferPool; + this.rejectDuplicateKeys = rejectDuplicateKeys; + } + + JsonObjectBuilderImpl(JsonObject object, BufferPool bufferPool) { + this.bufferPool = bufferPool; + valueMap = new LinkedHashMap<>(); + valueMap.putAll(object); + rejectDuplicateKeys = false; + } + + JsonObjectBuilderImpl(JsonObject object, BufferPool bufferPool, boolean rejectDuplicateKeys) { + this.bufferPool = bufferPool; + valueMap = new LinkedHashMap<>(); + valueMap.putAll(object); + this.rejectDuplicateKeys = rejectDuplicateKeys; + } + + JsonObjectBuilderImpl(Map<String, Object> map, BufferPool bufferPool) { + this.bufferPool = bufferPool; + valueMap = new LinkedHashMap<>(); + populate(map); + rejectDuplicateKeys = false; + } + + JsonObjectBuilderImpl(Map<String, Object> map, BufferPool bufferPool, boolean rejectDuplicateKeys) { + this.bufferPool = bufferPool; + valueMap = new LinkedHashMap<>(); + populate(map); + this.rejectDuplicateKeys = rejectDuplicateKeys; + } + + @Override + public JsonObjectBuilder add(String name, JsonValue value) { + validateName(name); + validateValue(value); + putValueMap(name, value); + return this; + } + + @Override + public JsonObjectBuilder add(String name, String value) { + validateName(name); + validateValue(value); + putValueMap(name, new JsonStringImpl(value)); + return this; + } + + @Override + public JsonObjectBuilder add(String name, BigInteger value) { + validateName(name); + validateValue(value); + putValueMap(name, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonObjectBuilder add(String name, BigDecimal value) { + validateName(name); + validateValue(value); + putValueMap(name, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonObjectBuilder add(String name, int value) { + validateName(name); + putValueMap(name, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonObjectBuilder add(String name, long value) { + validateName(name); + putValueMap(name, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonObjectBuilder add(String name, double value) { + validateName(name); + putValueMap(name, JsonNumberImpl.getJsonNumber(value)); + return this; + } + + @Override + public JsonObjectBuilder add(String name, boolean value) { + validateName(name); + putValueMap(name, value ? JsonValue.TRUE : JsonValue.FALSE); + return this; + } + + @Override + public JsonObjectBuilder addNull(String name) { + validateName(name); + putValueMap(name, JsonValue.NULL); + return this; + } + + @Override + public JsonObjectBuilder add(String name, JsonObjectBuilder builder) { + validateName(name); + if (builder == null) { + throw new NullPointerException(JsonMessages.OBJBUILDER_OBJECT_BUILDER_NULL()); + } + putValueMap(name, builder.build()); + return this; + } + + @Override + public JsonObjectBuilder add(String name, JsonArrayBuilder builder) { + validateName(name); + if (builder == null) { + throw new NullPointerException(JsonMessages.OBJBUILDER_ARRAY_BUILDER_NULL()); + } + putValueMap(name, builder.build()); + return this; + } + + @Override + public JsonObjectBuilder addAll(JsonObjectBuilder builder) { + if (builder == null) { + throw new NullPointerException(JsonMessages.OBJBUILDER_OBJECT_BUILDER_NULL()); + } + if (valueMap == null) { + this.valueMap = new LinkedHashMap<>(); + } + this.valueMap.putAll(builder.build()); + return this; + } + + @Override + public JsonObjectBuilder remove(String name) { + validateName(name); + this.valueMap.remove(name); + return this; + } + + @Override + public JsonObject build() { + Map<String, JsonValue> snapshot = (valueMap == null) + ? Collections.<String, JsonValue>emptyMap() + : Collections.unmodifiableMap(valueMap); + valueMap = null; + return new JsonObjectImpl(snapshot, bufferPool); + } + + private void populate(Map<String, Object> map) { + final Set<String> fields = map.keySet(); + for (String field : fields) { + Object value = map.get(field); + if (value != null && value instanceof Optional) { + ((Optional<?>) value).ifPresent(v -> + this.valueMap.put(field, MapUtil.handle(v, bufferPool))); + } else { + this.valueMap.put(field, MapUtil.handle(value, bufferPool)); + } + } + } + + private void putValueMap(String name, JsonValue value) { + if (valueMap == null) { + this.valueMap = new LinkedHashMap<>(); + } + JsonValue previousValue = valueMap.put(name, value); + if (rejectDuplicateKeys && previousValue != null) { + throw new IllegalStateException(JsonMessages.DUPLICATE_KEY(name)); + } + } + + private void validateName(String name) { + if (name == null) { + throw new NullPointerException(JsonMessages.OBJBUILDER_NAME_NULL()); + } + } + + private void validateValue(Object value) { + if (value == null) { + throw new NullPointerException(JsonMessages.OBJBUILDER_VALUE_NULL()); + } + } + + private static final class JsonObjectImpl extends AbstractMap<String, JsonValue> implements JsonObject { + private final Map<String, JsonValue> valueMap; // unmodifiable + private final BufferPool bufferPool; + private int hashCode; + + JsonObjectImpl(Map<String, JsonValue> valueMap, BufferPool bufferPool) { + this.valueMap = valueMap; + this.bufferPool = bufferPool; + } + + @Override + public JsonArray getJsonArray(String name) { + return (JsonArray)get(name); + } + + @Override + public JsonObject getJsonObject(String name) { + return (JsonObject)get(name); + } + + @Override + public JsonNumber getJsonNumber(String name) { + return (JsonNumber)get(name); + } + + @Override + public JsonString getJsonString(String name) { + return (JsonString)get(name); + } + + @Override + public String getString(String name) { + return getJsonString(name).getString(); + } + + @Override + public String getString(String name, String defaultValue) { + JsonValue value = get(name); + if (value instanceof JsonString) { + return ((JsonString) value).getString(); + } else { + return defaultValue; + } + } + + @Override + public int getInt(String name) { + return getJsonNumber(name).intValue(); + } + + @Override + public int getInt(String name, int defaultValue) { + JsonValue value = get(name); + if (value instanceof JsonNumber) { + return ((JsonNumber) value).intValue(); + } else { + return defaultValue; + } + } + + @Override + public boolean getBoolean(String name) { + JsonValue value = get(name); + if (value == null) { + throw new NullPointerException(); + } else if (value == JsonValue.TRUE) { + return true; + } else if (value == JsonValue.FALSE) { + return false; + } else { + throw new ClassCastException(); + } + } + + @Override + public boolean getBoolean(String name, boolean defaultValue) { + JsonValue value = get(name); + if (value == JsonValue.TRUE) { + return true; + } else if (value == JsonValue.FALSE) { + return false; + } else { + return defaultValue; + } + } + + @Override + public boolean isNull(String name) { + return get(name).equals(JsonValue.NULL); + } + + @Override + public ValueType getValueType() { + return ValueType.OBJECT; + } + + @Override + public Set<Entry<String, JsonValue>> entrySet() { + return valueMap.entrySet(); + } + + @Override + public int hashCode() { + if (hashCode == 0) { + hashCode = super.hashCode(); + } + return hashCode; + } + + @Override + public String toString() { + StringWriter sw = new StringWriter(); + try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool)) { + jw.write(this); + } + return sw.toString(); + } + + @Override + public JsonObject asJsonObject() { + return this; + } + + @Override + public int size() { + return valueMap.size(); + } + + @Override + public JsonValue get(Object key) { + return valueMap.get(key); + } + + @Override + public boolean containsKey(Object key) { + return valueMap.containsKey(key); + } + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonParserFactoryImpl.java b/impl/src/main/java/org/glassfish/json/JsonParserFactoryImpl.java new file mode 100644 index 0000000..fb6203c --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonParserFactoryImpl.java
@@ -0,0 +1,71 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.stream.JsonParserFactory; +import jakarta.json.stream.JsonParser; +import java.io.InputStream; +import java.io.Reader; +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.Map; + +/** + * @author Jitendra Kotamraju + */ +class JsonParserFactoryImpl implements JsonParserFactory { + private final Map<String, ?> config = Collections.emptyMap(); + private final BufferPool bufferPool; + + JsonParserFactoryImpl(BufferPool bufferPool) { + this.bufferPool = bufferPool; + } + + @Override + public JsonParser createParser(Reader reader) { + return new JsonParserImpl(reader, bufferPool); + } + + @Override + public JsonParser createParser(InputStream in) { + return new JsonParserImpl(in, bufferPool); + } + + @Override + public JsonParser createParser(InputStream in, Charset charset) { + return new JsonParserImpl(in, charset, bufferPool); + } + + @Override + public JsonParser createParser(JsonArray array) { + return new JsonStructureParser(array); + } + + @Override + public Map<String, ?> getConfigInUse() { + return config; + } + + @Override + public JsonParser createParser(JsonObject object) { + return new JsonStructureParser(object); + } +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonParserImpl.java b/impl/src/main/java/org/glassfish/json/JsonParserImpl.java new file mode 100644 index 0000000..62bf4d4 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonParserImpl.java
@@ -0,0 +1,586 @@ +/* + * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.math.BigDecimal; +import java.nio.charset.Charset; +import java.util.AbstractMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonLocation; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import jakarta.json.stream.JsonParsingException; + +import org.glassfish.json.JsonTokenizer.JsonToken; +import org.glassfish.json.api.BufferPool; + +/** + * JSON parser implementation. NoneContext, ArrayContext, ObjectContext is used + * to go to next parser state. + * + * @author Jitendra Kotamraju + * @author Kin-man Chung + */ +public class JsonParserImpl implements JsonParser { + + private final BufferPool bufferPool; + private final boolean rejectDuplicateKeys; + private Context currentContext = new NoneContext(); + private Event currentEvent; + + private final Stack stack = new Stack(); + private final JsonTokenizer tokenizer; + + public JsonParserImpl(Reader reader, BufferPool bufferPool) { + this(reader, bufferPool, false); + } + + public JsonParserImpl(Reader reader, BufferPool bufferPool, boolean rejectDuplicateKeys) { + this.bufferPool = bufferPool; + this.rejectDuplicateKeys = rejectDuplicateKeys; + tokenizer = new JsonTokenizer(reader, bufferPool); + } + + public JsonParserImpl(InputStream in, BufferPool bufferPool) { + this(in, bufferPool, false); + } + + public JsonParserImpl(InputStream in, BufferPool bufferPool, boolean rejectDuplicateKeys) { + this.bufferPool = bufferPool; + this.rejectDuplicateKeys = rejectDuplicateKeys; + UnicodeDetectingInputStream uin = new UnicodeDetectingInputStream(in); + tokenizer = new JsonTokenizer(new InputStreamReader(uin, uin.getCharset()), bufferPool); + } + + public JsonParserImpl(InputStream in, Charset encoding, BufferPool bufferPool) { + this(in, encoding, bufferPool, false); + } + + public JsonParserImpl(InputStream in, Charset encoding, BufferPool bufferPool, boolean rejectDuplicateKeys) { + this.bufferPool = bufferPool; + this.rejectDuplicateKeys = rejectDuplicateKeys; + tokenizer = new JsonTokenizer(new InputStreamReader(in, encoding), bufferPool); + } + + @Override + public String getString() { + if (currentEvent == Event.KEY_NAME || currentEvent == Event.VALUE_STRING + || currentEvent == Event.VALUE_NUMBER) { + return tokenizer.getValue(); + } + throw new IllegalStateException( + JsonMessages.PARSER_GETSTRING_ERR(currentEvent)); + } + + @Override + public boolean isIntegralNumber() { + if (currentEvent != Event.VALUE_NUMBER) { + throw new IllegalStateException( + JsonMessages.PARSER_ISINTEGRALNUMBER_ERR(currentEvent)); + } + return tokenizer.isIntegral(); + } + + @Override + public int getInt() { + if (currentEvent != Event.VALUE_NUMBER) { + throw new IllegalStateException( + JsonMessages.PARSER_GETINT_ERR(currentEvent)); + } + return tokenizer.getInt(); + } + + boolean isDefinitelyInt() { + return tokenizer.isDefinitelyInt(); + } + + boolean isDefinitelyLong() { + return tokenizer.isDefinitelyLong(); + } + + @Override + public long getLong() { + if (currentEvent != Event.VALUE_NUMBER) { + throw new IllegalStateException( + JsonMessages.PARSER_GETLONG_ERR(currentEvent)); + } + return tokenizer.getLong(); + } + + @Override + public BigDecimal getBigDecimal() { + if (currentEvent != Event.VALUE_NUMBER) { + throw new IllegalStateException( + JsonMessages.PARSER_GETBIGDECIMAL_ERR(currentEvent)); + } + return tokenizer.getBigDecimal(); + } + + @Override + public JsonArray getArray() { + if (currentEvent != Event.START_ARRAY) { + throw new IllegalStateException( + JsonMessages.PARSER_GETARRAY_ERR(currentEvent)); + } + return getArray(new JsonArrayBuilderImpl(bufferPool)); + } + + @Override + public JsonObject getObject() { + if (currentEvent != Event.START_OBJECT) { + throw new IllegalStateException( + JsonMessages.PARSER_GETOBJECT_ERR(currentEvent)); + } + return getObject(new JsonObjectBuilderImpl(bufferPool, rejectDuplicateKeys)); + } + + @Override + public JsonValue getValue() { + switch (currentEvent) { + case START_ARRAY: + return getArray(new JsonArrayBuilderImpl(bufferPool)); + case START_OBJECT: + return getObject(new JsonObjectBuilderImpl(bufferPool)); + case KEY_NAME: + case VALUE_STRING: + return new JsonStringImpl(getString()); + case VALUE_NUMBER: + if (isDefinitelyInt()) { + return JsonNumberImpl.getJsonNumber(getInt()); + } else if (isDefinitelyLong()) { + return JsonNumberImpl.getJsonNumber(getLong()); + } + return JsonNumberImpl.getJsonNumber(getBigDecimal()); + case VALUE_TRUE: + return JsonValue.TRUE; + case VALUE_FALSE: + return JsonValue.FALSE; + case VALUE_NULL: + return JsonValue.NULL; + case END_ARRAY: + case END_OBJECT: + default: + throw new IllegalStateException(JsonMessages.PARSER_GETVALUE_ERR(currentEvent)); + } + } + + @Override + public Stream<JsonValue> getArrayStream() { + if (currentEvent != Event.START_ARRAY) { + throw new IllegalStateException( + JsonMessages.PARSER_GETARRAY_ERR(currentEvent)); + } + Spliterator<JsonValue> spliterator = + new Spliterators.AbstractSpliterator<JsonValue>(Long.MAX_VALUE, Spliterator.ORDERED) { + @Override + public Spliterator<JsonValue> trySplit() { + return null; + } + @Override + public boolean tryAdvance(Consumer<? super JsonValue> action) { + if (action == null) { + throw new NullPointerException(); + } + if (! hasNext()) { + return false; + } + if (next() == JsonParser.Event.END_ARRAY) { + return false; + } + action.accept(getValue()); + return true; + } + }; + return StreamSupport.stream(spliterator, false); + } + + @Override + public Stream<Map.Entry<String, JsonValue>> getObjectStream() { + if (currentEvent != Event.START_OBJECT) { + throw new IllegalStateException( + JsonMessages.PARSER_GETOBJECT_ERR(currentEvent)); + } + Spliterator<Map.Entry<String, JsonValue>> spliterator = + new Spliterators.AbstractSpliterator<Map.Entry<String, JsonValue>>(Long.MAX_VALUE, Spliterator.ORDERED) { + @Override + public Spliterator<Map.Entry<String,JsonValue>> trySplit() { + return null; + } + @Override + public boolean tryAdvance(Consumer<? super Map.Entry<String, JsonValue>> action) { + if (action == null) { + throw new NullPointerException(); + } + if (! hasNext()) { + return false; + } + JsonParser.Event e = next(); + if (e == JsonParser.Event.END_OBJECT) { + return false; + } + if (e != JsonParser.Event.KEY_NAME) { + throw new JsonException(JsonMessages.INTERNAL_ERROR()); + } + String key = getString(); + if (! hasNext()) { + throw new JsonException(JsonMessages.INTERNAL_ERROR()); + } + next(); + JsonValue value = getValue(); + action.accept(new AbstractMap.SimpleImmutableEntry<>(key, value)); + return true; + } + }; + return StreamSupport.stream(spliterator, false); + } + + @Override + public Stream<JsonValue> getValueStream() { + if (! (currentContext instanceof NoneContext)) { + throw new IllegalStateException( + JsonMessages.PARSER_GETVALUESTREAM_ERR()); + } + Spliterator<JsonValue> spliterator = + new Spliterators.AbstractSpliterator<JsonValue>(Long.MAX_VALUE, Spliterator.ORDERED) { + @Override + public Spliterator<JsonValue> trySplit() { + return null; + } + @Override + public boolean tryAdvance(Consumer<? super JsonValue> action) { + if (action == null) { + throw new NullPointerException(); + } + if (! hasNext()) { + return false; + } + next(); + action.accept(getValue()); + return true; + } + }; + return StreamSupport.stream(spliterator, false); + } + + @Override + public void skipArray() { + if (currentEvent == Event.START_ARRAY) { + currentContext.skip(); + currentContext = stack.pop(); + currentEvent = Event.END_ARRAY; + } + } + + @Override + public void skipObject() { + if (currentEvent == Event.START_OBJECT) { + currentContext.skip(); + currentContext = stack.pop(); + currentEvent = Event.END_OBJECT; + } + } + + private JsonArray getArray(JsonArrayBuilder builder) { + while(hasNext()) { + JsonParser.Event e = next(); + if (e == JsonParser.Event.END_ARRAY) { + return builder.build(); + } + builder.add(getValue()); + } + throw parsingException(JsonToken.EOF, "[CURLYOPEN, SQUAREOPEN, STRING, NUMBER, TRUE, FALSE, NULL, SQUARECLOSE]"); + } + + private JsonObject getObject(JsonObjectBuilder builder) { + while(hasNext()) { + JsonParser.Event e = next(); + if (e == JsonParser.Event.END_OBJECT) { + return builder.build(); + } + String key = getString(); + next(); + builder.add(key, getValue()); + } + throw parsingException(JsonToken.EOF, "[STRING, CURLYCLOSE]"); + } + + @Override + public JsonLocation getLocation() { + return tokenizer.getLocation(); + } + + public JsonLocation getLastCharLocation() { + return tokenizer.getLastCharLocation(); + } + + @Override + public boolean hasNext() { + if (stack.isEmpty() && (currentEvent != null && currentEvent.compareTo(Event.KEY_NAME) > 0)) { + JsonToken token = tokenizer.nextToken(); + if (token != JsonToken.EOF) { + throw new JsonParsingException(JsonMessages.PARSER_EXPECTED_EOF(token), + getLastCharLocation()); + } + return false; + } else if (!stack.isEmpty() && !tokenizer.hasNextToken()) { + currentEvent = currentContext.getNextEvent(); + return false; + } + return true; + } + + @Override + public Event next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return currentEvent = currentContext.getNextEvent(); + } + + @Override + public void close() { + try { + tokenizer.close(); + } catch (IOException e) { + throw new JsonException(JsonMessages.PARSER_TOKENIZER_CLOSE_IO(), e); + } + } + + // Using the optimized stack impl as we don't require other things + // like iterator etc. + private static final class Stack { + private Context head; + + private void push(Context context) { + context.next = head; + head = context; + } + + private Context pop() { + if (head == null) { + throw new NoSuchElementException(); + } + Context temp = head; + head = head.next; + return temp; + } + + private Context peek() { + return head; + } + + private boolean isEmpty() { + return head == null; + } + } + + private abstract class Context { + Context next; + abstract Event getNextEvent(); + abstract void skip(); + } + + private final class NoneContext extends Context { + @Override + public Event getNextEvent() { + // Handle 1. { 2. [ 3. value + JsonToken token = tokenizer.nextToken(); + if (token == JsonToken.CURLYOPEN) { + stack.push(currentContext); + currentContext = new ObjectContext(); + return Event.START_OBJECT; + } else if (token == JsonToken.SQUAREOPEN) { + stack.push(currentContext); + currentContext = new ArrayContext(); + return Event.START_ARRAY; + } else if (token.isValue()) { + return token.getEvent(); + } + throw parsingException(token, "[CURLYOPEN, SQUAREOPEN, STRING, NUMBER, TRUE, FALSE, NULL]"); + } + + @Override + void skip() { + // no-op + } + } + + private JsonParsingException parsingException(JsonToken token, String expectedTokens) { + JsonLocation location = getLastCharLocation(); + return new JsonParsingException( + JsonMessages.PARSER_INVALID_TOKEN(token, location, expectedTokens), location); + } + + private final class ObjectContext extends Context { + private boolean firstValue = true; + + /* + * Some more things could be optimized. For example, instead + * tokenizer.nextToken(), one could use tokenizer.matchColonToken() to + * match ':'. That might optimize a bit, but will fragment nextToken(). + * I think the current one is more readable. + * + */ + @Override + public Event getNextEvent() { + // Handle 1. } 2. name:value 3. ,name:value + JsonToken token = tokenizer.nextToken(); + if (token == JsonToken.EOF) { + switch (currentEvent) { + case START_OBJECT: + throw parsingException(token, "[STRING, CURLYCLOSE]"); + case KEY_NAME: + throw parsingException(token, "[COLON]"); + default: + throw parsingException(token, "[COMMA, CURLYCLOSE]"); + } + } else if (currentEvent == Event.KEY_NAME) { + // Handle 1. :value + if (token != JsonToken.COLON) { + throw parsingException(token, "[COLON]"); + } + token = tokenizer.nextToken(); + if (token.isValue()) { + return token.getEvent(); + } else if (token == JsonToken.CURLYOPEN) { + stack.push(currentContext); + currentContext = new ObjectContext(); + return Event.START_OBJECT; + } else if (token == JsonToken.SQUAREOPEN) { + stack.push(currentContext); + currentContext = new ArrayContext(); + return Event.START_ARRAY; + } + throw parsingException(token, "[CURLYOPEN, SQUAREOPEN, STRING, NUMBER, TRUE, FALSE, NULL]"); + } else { + // Handle 1. } 2. name 3. ,name + if (token == JsonToken.CURLYCLOSE) { + currentContext = stack.pop(); + return Event.END_OBJECT; + } + if (firstValue) { + firstValue = false; + } else { + if (token != JsonToken.COMMA) { + throw parsingException(token, "[COMMA]"); + } + token = tokenizer.nextToken(); + } + if (token == JsonToken.STRING) { + return Event.KEY_NAME; + } + throw parsingException(token, "[STRING]"); + } + } + + @Override + void skip() { + JsonToken token; + int depth = 1; + do { + token = tokenizer.nextToken(); + switch (token) { + case CURLYCLOSE: + depth--; + break; + case CURLYOPEN: + depth++; + break; + } + } while (!(token == JsonToken.CURLYCLOSE && depth == 0)); + } + + } + + private final class ArrayContext extends Context { + private boolean firstValue = true; + + // Handle 1. ] 2. value 3. ,value + @Override + public Event getNextEvent() { + JsonToken token = tokenizer.nextToken(); + if (token == JsonToken.EOF) { + switch (currentEvent) { + case START_ARRAY: + throw parsingException(token, "[CURLYOPEN, SQUAREOPEN, STRING, NUMBER, TRUE, FALSE, NULL]"); + default: + throw parsingException(token, "[COMMA, CURLYCLOSE]"); + } + } + if (token == JsonToken.SQUARECLOSE) { + currentContext = stack.pop(); + return Event.END_ARRAY; + } + if (firstValue) { + firstValue = false; + } else { + if (token != JsonToken.COMMA) { + throw parsingException(token, "[COMMA]"); + } + token = tokenizer.nextToken(); + } + if (token.isValue()) { + return token.getEvent(); + } else if (token == JsonToken.CURLYOPEN) { + stack.push(currentContext); + currentContext = new ObjectContext(); + return Event.START_OBJECT; + } else if (token == JsonToken.SQUAREOPEN) { + stack.push(currentContext); + currentContext = new ArrayContext(); + return Event.START_ARRAY; + } + throw parsingException(token, "[CURLYOPEN, SQUAREOPEN, STRING, NUMBER, TRUE, FALSE, NULL]"); + } + + @Override + void skip() { + JsonToken token; + int depth = 1; + do { + token = tokenizer.nextToken(); + switch (token) { + case SQUARECLOSE: + depth--; + break; + case SQUAREOPEN: + depth++; + break; + } + } while (!(token == JsonToken.SQUARECLOSE && depth == 0)); + } + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonPatchBuilderImpl.java b/impl/src/main/java/org/glassfish/json/JsonPatchBuilderImpl.java new file mode 100644 index 0000000..78e3982 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonPatchBuilderImpl.java
@@ -0,0 +1,337 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonException; +import jakarta.json.JsonPatch; +import jakarta.json.JsonPatch.Operation; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; + +/** + * A builder for constructing a JSON Patch by adding + * JSON Patch operations incrementally. + * <p> + * The following illustrates the approach. + * <pre> + * JsonPatchBuilder builder = Json.createPatchBuilder(); + * JsonPatch patch = builder.add("/John/phones/office", "1234-567") + * .remove("/Amy/age") + * .build(); + * </pre> + * The result is equivalent to the following JSON Patch. + * <pre> + * [ + * {"op" = "add", "path" = "/John/phones/office", "value" = "1234-567"}, + * {"op" = "remove", "path" = "/Amy/age"} + * ] </pre> + * + * @since 1.1 + */ +public final class JsonPatchBuilderImpl implements JsonPatchBuilder { + + private final JsonArrayBuilder builder; + + /** + * Creates a JsonPatchBuilderImpl, starting with the specified + * JSON Patch + * @param patch the JSON Patch + */ + public JsonPatchBuilderImpl(JsonArray patch) { + builder = new JsonArrayBuilderImpl(patch, JsonUtil.getInternalBufferPool()); + } + + /** + * Creates JsonPatchBuilderImpl with empty JSON Patch + */ + public JsonPatchBuilderImpl() { + builder = new JsonArrayBuilderImpl(JsonUtil.getInternalBufferPool()); + } + + /** + * A convenience method for {@code new JsonPatchImpl(build()).apply(target)}. + * The target is not modified by the patch. + * + * @param <T> the target type, must be a subtype of {@link JsonStructure} + * @param target the target to apply the patch operations + * @return the transformed target after the patch + * @throws JsonException if the supplied JSON Patch is malformed or if + * it contains references to non-existing members + */ + public <T extends JsonStructure> T apply(T target) { + return build().apply(target); + } + + /** + * Adds an "add" JSON Patch operation. + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder add(String path, JsonValue value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.ADD.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds an "add" JSON Patch operation + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder add(String path, String value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.ADD.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds an "add" JSON Patch operation + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder add(String path, int value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.ADD.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds an "add" JSON Patch operation + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder add(String path, boolean value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.ADD.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds a "remove" JSON Patch operation. + * @param path the "path" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder remove(String path) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.REMOVE.operationName()) + .add("path", path) + ); + return this; + } + + /** + * Adds a "replace" JSON Patch operation. + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder replace(String path, JsonValue value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.REPLACE.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds a "replace" JSON Patch operation. + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder replace(String path, String value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.REPLACE.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds a "replace" JSON Patch operation. + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder replace(String path, int value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.REPLACE.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds a "replace" JSON Patch operation. + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder replace(String path, boolean value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.REPLACE.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds a "move" JSON Patch operation. + * @param path the "path" member of the operation + * @param from the "from" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder move(String path, String from) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.MOVE.operationName()) + .add("path", path) + .add("from", from) + ); + return this; + } + + /** + * Adds a "copy" JSON Patch operation. + * @param path the "path" member of the operation + * @param from the "from" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder copy(String path, String from) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.COPY.operationName()) + .add("path", path) + .add("from", from) + ); + return this; + } + + /** + * Adds a "test" JSON Patch operation. + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder test(String path, JsonValue value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.TEST.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds a "test" JSON Patch operation. + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder test(String path, String value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.TEST.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds a "test" JSON Patch operation. + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder test(String path, int value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.TEST.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Adds a "test" JSON Patch operation. + * @param path the "path" member of the operation + * @param value the "value" member of the operation + * @return this JsonPatchBuilder + */ + @Override + public JsonPatchBuilder test(String path, boolean value) { + builder.add(new JsonObjectBuilderImpl(JsonUtil.getInternalBufferPool()) + .add("op", Operation.TEST.operationName()) + .add("path", path) + .add("value", value) + ); + return this; + } + + /** + * Returns the patch operations in a JsonArray + * @return the patch operations in a JsonArray + */ + public JsonArray buildAsJsonArray() { + return builder.build(); + } + + /** + * Returns the patch operation in a JsonPatch + * @return the patch operation in a JsonPatch + */ + @Override + public JsonPatch build() { + return new JsonPatchImpl(buildAsJsonArray()); + } +} +
diff --git a/impl/src/main/java/org/glassfish/json/JsonPatchImpl.java b/impl/src/main/java/org/glassfish/json/JsonPatchImpl.java new file mode 100644 index 0000000..1f9352d --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonPatchImpl.java
@@ -0,0 +1,321 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatch; +import jakarta.json.JsonPatch.Operation; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.JsonPointer; +import jakarta.json.JsonString; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; +import jakarta.json.JsonValue.ValueType; + +/** + * This class is an immutable representation of a JSON Patch as specified in + * <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>. + * <p>A {@code JsonPatch} can be instantiated with {@link Json#createPatch(JsonArray)} + * by specifying the patch operations in a JSON Patch. Alternately, it + * can also be constructed with a {@link JsonPatchBuilder}. + * </p> + * The following illustrates both approaches. + * <p>1. Construct a JsonPatch with a JSON Patch. + * <pre>{@code + * JsonArray contacts = ... // The target to be patched + * JsonArray patch = ... ; // JSON Patch + * JsonPatch jsonpatch = Json.createPatch(patch); + * JsonArray result = jsonpatch.apply(contacts); + * } </pre> + * 2. Construct a JsonPatch with JsonPatchBuilder. + * <pre>{@code + * JsonPatchBuilder builder = Json.createPatchBuilder(); + * JsonArray result = builder.add("/John/phones/office", "1234-567") + * .remove("/Amy/age") + * .build() + * .apply(contacts); + * } </pre> + * + * @since 1.1 + */ +public class JsonPatchImpl implements JsonPatch { + + private final JsonArray patch; + + /** + * Constructs a JsonPatchImpl + * @param patch the JSON Patch + */ + public JsonPatchImpl(JsonArray patch) { + this.patch = patch; + } + + /** + * Compares this {@code JsonPatchImpl} with another object. + * @param obj the object to compare this {@code JsonPatchImpl} against + * @return true if the given object is a {@code JsonPatchImpl} with the same + * reference tokens as this one, false otherwise. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || obj.getClass() != JsonPatchImpl.class) + return false; + return patch.equals(((JsonPatchImpl)obj).patch); + } + + /** + * Returns the hash code value for this {@code JsonPatchImpl}. + * + * @return the hash code value for this {@code JsonPatchImpl} object + */ + @Override + public int hashCode() { + return patch.hashCode(); + } + + /** + * Returns the JSON Patch text + * @return the JSON Patch text + */ + @Override + public String toString() { + return patch.toString(); + } + + /** + * Applies the patch operations to the specified {@code target}. + * The target is not modified by the patch. + * + * @param target the target to apply the patch operations + * @return the transformed target after the patch + * @throws JsonException if the supplied JSON Patch is malformed or if + * it contains references to non-existing members + */ + @Override + public JsonStructure apply(JsonStructure target) { + + JsonStructure result = target; + + for (JsonValue operation: patch) { + if (operation.getValueType() != ValueType.OBJECT) { + throw new JsonException(JsonMessages.PATCH_MUST_BE_ARRAY()); + } + result = apply(result, (JsonObject) operation); + } + return result; + } + + @Override + public JsonArray toJsonArray() { + return patch; + } + + /** + * Generates a JSON Patch from the source and target {@code JsonStructure}. + * The generated JSON Patch need not be unique. + * @param source the source + * @param target the target, must be the same type as the source + * @return a JSON Patch which when applied to the source, yields the target + */ + public static JsonArray diff(JsonStructure source, JsonStructure target) { + return (new DiffGenerator()).diff(source, target); + } + + /** + * Applies a JSON Patch operation to the target. + * @param target the target to apply the operation + * @param operation the JSON Patch operation + * @return the target after the patch + */ + private JsonStructure apply(JsonStructure target, JsonObject operation) { + + JsonPointer pointer = getPointer(operation, "path"); + JsonPointer from; + JsonString op = operation.getJsonString("op"); + if (op == null) { + throw new JsonException(JsonMessages.PATCH_OPERATION_MISSING()); + } + switch (Operation.fromOperationName(op.getString())) { + case ADD: + return pointer.add(target, getValue(operation)); + case REPLACE: + return pointer.replace(target, getValue(operation)); + case REMOVE: + return pointer.remove(target); + case COPY: + from = getPointer(operation, "from"); + return pointer.add(target, from.getValue(target)); + case MOVE: + // Check if from is a proper prefix of path + String dest = operation.getString("path"); + String src = operation.getString("from"); + if (dest.startsWith(src) && src.length() < dest.length()) { + throw new JsonException(JsonMessages.PATCH_MOVE_PROPER_PREFIX(src, dest)); + } + from = getPointer(operation, "from"); + // Check if 'from' exists in target object + if (!from.containsValue(target)) { + throw new JsonException(JsonMessages.PATCH_MOVE_TARGET_NULL(src)); + } + if (pointer.equals(from)) { + // nop + return target; + } + return pointer.add(from.remove(target), from.getValue(target)); + case TEST: + if (! getValue(operation).equals(pointer.getValue(target))) { + throw new JsonException(JsonMessages.PATCH_TEST_FAILED(operation.getString("path"), getValue(operation).toString())); + } + return target; + default: + throw new JsonException(JsonMessages.PATCH_ILLEGAL_OPERATION(operation.getString("op"))); + } + } + + private JsonPointer getPointer(JsonObject operation, String member) { + JsonString pointerString = operation.getJsonString(member); + if (pointerString == null) { + missingMember(operation.getString("op"), member); + } + return new JsonPointerImpl(pointerString.getString()); + } + + private JsonValue getValue(JsonObject operation) { + JsonValue value = operation.get("value"); + if (value == null) { + missingMember(operation.getString("op"), "value"); + } + return value; + } + + private void missingMember(String op, String member) { + throw new JsonException(JsonMessages.PATCH_MEMBER_MISSING(op, member)); + } + + static class DiffGenerator { + private JsonPatchBuilder builder; + + JsonArray diff(JsonStructure source, JsonStructure target) { + builder = new JsonPatchBuilderImpl(); + diff("", source, target); + return builder.build().toJsonArray(); + } + + private void diff(String path, JsonValue source, JsonValue target) { + if (source.equals(target)) { + return; + } + ValueType s = source.getValueType(); + ValueType t = target.getValueType(); + if (s == ValueType.OBJECT && t == ValueType.OBJECT) { + diffObject(path, (JsonObject) source, (JsonObject) target); + } else if (s == ValueType.ARRAY && t == ValueType.ARRAY) { + diffArray(path, (JsonArray) source, (JsonArray) target); + } else { + builder.replace(path, target); + } + } + + private void diffObject(String path, JsonObject source, JsonObject target) { + source.forEach((key, value) -> { + if (target.containsKey(key)) { + diff(path + '/' + Json.encodePointer(key), value, target.get(key)); + } else { + builder.remove(path + '/' + Json.encodePointer(key)); + } + }); + target.forEach((key, value) -> { + if (! source.containsKey(key)) { + builder.add(path + '/' + Json.encodePointer(key), value); + } + }); + } + + /* + * For array element diff, find the longest common subsequence, per + * http://en.wikipedia.org/wiki/Longest_common_subsequence_problem . + * We modify the algorithm to generate a replace if possible. + */ + private void diffArray(String path, JsonArray source, JsonArray target) { + /* The array c keeps track of length of the subsequence. To avoid + * computing the equality of array elements again, we + * left shift its value by 1, and use the low order bit to mark + * that two items are equal. + */ + int m = source.size(); + int n = target.size(); + int [][] c = new int[m+1][n+1]; + for (int i = 0; i < m+1; i++) + c[i][0] = 0; + for (int i = 0; i < n+1; i++) + c[0][i] = 0; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (source.get(i).equals(target.get(j))) { + c[i+1][j+1] = ((c[i][j]) & ~1) + 3; + // 3 = (1 << 1) | 1; + } else { + c[i+1][j+1] = Math.max(c[i+1][j], c[i][j+1]) & ~1; + } + } + } + + emit(path, source, target, c, m, n); + } + + private void emit(final String path, + final JsonArray source, + final JsonArray target, + final int[][] c, + final int i, + final int j) { + if (i == 0) { + if (j > 0) { + emit(path, source, target, c, i, j - 1); + builder.add(path + '/' + (j - 1), target.get(j - 1)); + } + } else if (j == 0) { + if (i > 0) { + builder.remove(path + '/' + (i - 1)); + emit(path, source, target, c, i - 1, j); + } + } else if ((c[i][j] & 1) == 1) { + emit(path, source, target, c, i - 1, j - 1); + } else { + final int f = c[i][j-1] >> 1; + final int g = c[i-1][j] >> 1; + if (f > g) { + emit(path, source, target, c, i, j - 1); + builder.add(path + '/' + (j - 1), target.get(j - 1)); + } else if (f < g) { + builder.remove(path + '/' + (i - 1)); + emit(path, source, target, c, i - 1, j); + } else { // f == g) { + diff(path + '/' + (i - 1), source.get(i - 1), + target.get(j - 1)); + emit(path, source, target, c, i - 1, j - 1); + } + } + } + } +} +
diff --git a/impl/src/main/java/org/glassfish/json/JsonPointerImpl.java b/impl/src/main/java/org/glassfish/json/JsonPointerImpl.java new file mode 100644 index 0000000..b91a576 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonPointerImpl.java
@@ -0,0 +1,300 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; +import java.io.Serializable; +import java.util.function.BiFunction; + +/** + * <p>This class is an immutable representation of a JSON Pointer as specified in + * <a href="http://tools.ietf.org/html/rfc6901">RFC 6901</a>. + * </p> + * <p> A JSON Pointer, when applied to a target {@link JsonValue}, + * defines a reference location in the target.</p> + * <p> An empty JSON Pointer string defines a reference to the target itself.</p> + * <p> If the JSON Pointer string is non-empty, it must be a sequence + * of '/' prefixed tokens, and the target must either be a {@link JsonArray} + * or {@link JsonObject}. If the target is a {@code JsonArray}, the pointer + * defines a reference to an array element, and the last token specifies the index. + * If the target is a {@link JsonObject}, the pointer defines a reference to a + * name/value pair, and the last token specifies the name. + * </p> + * <p> The method {@link #getValue getValue()} returns the referenced value. + * The methods {@link #add add()}, {@link #replace replace()}, + * and {@link #remove remove()} executes the operations specified in + * <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>. </p> + * + * @since 1.1 + */ + +public final class JsonPointerImpl implements JsonPointer, Serializable { + + private static final long serialVersionUID = -8123110179640843141L; + private final String[] tokens; + private final String jsonPointer; + + /** + * Constructs and initializes a JsonPointerImpl. + * @param jsonPointer the JSON Pointer string + * @throws NullPointerException if {@code jsonPointer} is {@code null} + * @throws JsonException if {@code jsonPointer} is not a valid JSON Pointer + */ + public JsonPointerImpl(String jsonPointer) { + this.jsonPointer = jsonPointer; + tokens = jsonPointer.split("/", -1); // keep the trailing blanks + if (! "".equals(tokens[0])) { + throw new JsonException(JsonMessages.POINTER_FORMAT_INVALID()); + } + for (int i = 1; i < tokens.length; i++) { + String token = tokens[i]; + StringBuilder reftoken = new StringBuilder(); + for (int j = 0; j < token.length(); j++) { + char ch = token.charAt(j); + if (ch == '~' && j < token.length() - 1) { + char ch1 = token.charAt(j+1); + if (ch1 == '0') { + ch = '~'; j++; + } else if (ch1 == '1') { + ch = '/'; j++; + } + } + reftoken.append(ch); + } + tokens[i] = reftoken.toString(); + } + } + + /** + * Compares this {@code JsonPointer} with another object. + * @param obj the object to compare this {@code JsonPointer} against + * @return true if the given object is a {@code JsonPointer} with the same + * reference tokens as this one, false otherwise. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || obj.getClass() != JsonPointerImpl.class) + return false; + return jsonPointer.equals(((JsonPointerImpl)obj).jsonPointer); + } + + /** + * Returns the hash code value for this {@code JsonPointer} object. + * The hash code of this object is defined by the hash codes of it's reference tokens. + * + * @return the hash code value for this {@code JsonPointer} object + */ + @Override + public int hashCode() { + return jsonPointer.hashCode(); + } + + /** + * Returns {@code true} if there is a value at the referenced location in the specified {@code target}. + * + * @param target the target referenced by this {@code JsonPointer} + * @return {@code true} if this pointer points to a value in a specified {@code target}. + */ + @Override + public boolean containsValue(JsonStructure target) { + NodeReference[] refs = getReferences(target); + return refs[0].contains(); + } + + /** + * Returns the value at the referenced location in the specified {@code target} + * + * @param target the target referenced by this {@code JsonPointer} + * @return the referenced value in the target. + * @throws NullPointerException if {@code target} is null + * @throws JsonException if the referenced value does not exist + */ + @Override + public JsonValue getValue(JsonStructure target) { + NodeReference[] refs = getReferences(target); + return refs[0].get(); + } + + /** + * Adds or replaces a value at the referenced location in the specified + * {@code target} with the specified {@code value}. + * <ol> + * <li>If the reference is the target (empty JSON Pointer string), + * the specified {@code value}, which must be the same type as + * specified {@code target}, is returned.</li> + * <li>If the reference is an array element, the specified {@code value} is inserted + * into the array, at the referenced index. The value currently at that location, and + * any subsequent values, are shifted to the right (adds one to the indices). + * Index starts with 0. If the reference is specified with a "-", or if the + * index is equal to the size of the array, the value is appended to the array.</li> + * <li>If the reference is a name/value pair of a {@code JsonObject}, and the + * referenced value exists, the value is replaced by the specified {@code value}. + * If the value does not exist, a new name/value pair is added to the object.</li> + * </ol> + * + * @param target the target referenced by this {@code JsonPointer} + * @param value the value to be added + * @return the transformed {@code target} after the value is added. + * @throws NullPointerException if {@code target} is {@code null} + * @throws JsonException if the reference is an array element and + * the index is out of range ({@code index < 0 || index > array size}), + * or if the pointer contains references to non-existing objects or arrays. + */ + @Override + public JsonStructure add(JsonStructure target, JsonValue value) { + return execute(NodeReference::add, target, value); + } + + /** + * Replaces the value at the referenced location in the specified + * {@code target} with the specified {@code value}. + * + * @param target the target referenced by this {@code JsonPointer} + * @param value the value to be stored at the referenced location + * @return the transformed {@code target} after the value is replaced. + * @throws NullPointerException if {@code target} is {@code null} + * @throws JsonException if the referenced value does not exist, + * or if the reference is the target. + */ + @Override + public JsonStructure replace(JsonStructure target, JsonValue value) { + return execute(NodeReference::replace, target, value); + } + + /** + * Removes the value at the reference location in the specified {@code target} + * + * @param target the target referenced by this {@code JsonPointer} + * @return the transformed {@code target} after the value is removed. + * @throws NullPointerException if {@code target} is {@code null} + * @throws JsonException if the referenced value does not exist, + * or if the reference is the target. + */ + @Override + public JsonStructure remove(JsonStructure target) { + return execute((r,v)->r.remove(), target, null); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return jsonPointer; + } + + /** + * Executes the operation + * @param op a {code BiFunction} used to specify the operation to execute on + * the leaf node of the Json Pointer + * @param target the target JsonStructure for this JsonPointer + * @param value the JsonValue for add and replace, can be null for getvalue and remove + */ + private JsonStructure execute(BiFunction<NodeReference, JsonValue, JsonStructure> op, + JsonStructure target, JsonValue value) { + + NodeReference[] refs = getReferences(target); + JsonStructure result = op.apply(refs[0], value); + for (int i = 1; i < refs.length; i++) { + result = refs[i].replace(result); + } + return result; + } + + /** + * Computes the {@code NodeReference}s for each node on the path of + * the JSON Pointer, in reverse order, starting from the leaf node + */ + private NodeReference[] getReferences(JsonStructure target) { + NodeReference[] references; + // First check if this is a reference to a JSON value tree + if (tokens.length == 1) { + references = new NodeReference[1]; + references[0] = NodeReference.of(target); + return references; + } + + references = new NodeReference[tokens.length-1]; + JsonValue value = target; + int s = tokens.length; + for (int i = 1; i < s; i++) { + // Start with index 1, skipping the "" token + switch (value.getValueType()) { + case OBJECT: + JsonObject object = (JsonObject) value; + references[s-i-1] = NodeReference.of(object, tokens[i]); + if (i < s-1) { + value = object.get(tokens[i]); + if (value == null) { + // Except for the last name, the mapping must exist + throw new JsonException(JsonMessages.POINTER_MAPPING_MISSING(object, tokens[i])); + } + } + break; + case ARRAY: + int index = getIndex(tokens[i]); + JsonArray array = (JsonArray) value; + references[s-i-1] = NodeReference.of(array, index); + if (i < s-1 && index != -1) { + if (index >= array.size()) { + throw new JsonException(JsonMessages.NODEREF_ARRAY_INDEX_ERR(index, array.size())); + } + // The last array index in the path can have index value of -1 + // ("-" in the JSON pointer) + value = array.get(index); + } + break; + default: + throw new JsonException(JsonMessages.POINTER_REFERENCE_INVALID(value.getValueType())); + } + } + return references; + } + + /** + * Computes the array index + * @param token the input string token + * @return the array index. -1 if the token is "-" + * @throws JsonException if the string token is not in correct format + */ + static private int getIndex(String token) { + if (token == null || token.length() == 0) { + throw new JsonException(JsonMessages.POINTER_ARRAY_INDEX_ERR(token)); + } + if (token.equals("-")) { + return -1; + } + if (token.equals("0")) { + return 0; + } + if (token.charAt(0) == '+' || token.charAt(0) == '-') { + throw new JsonException(JsonMessages.POINTER_ARRAY_INDEX_ERR(token)); + } + try { + return Integer.parseInt(token); + } catch (NumberFormatException ex) { + throw new JsonException(JsonMessages.POINTER_ARRAY_INDEX_ILLEGAL(token), ex); + } + } +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonPrettyGeneratorImpl.java b/impl/src/main/java/org/glassfish/json/JsonPrettyGeneratorImpl.java new file mode 100644 index 0000000..f1c28a2 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonPrettyGeneratorImpl.java
@@ -0,0 +1,106 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.stream.JsonGenerator; +import java.io.OutputStream; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * @author Jitendra Kotamraju + */ +public class JsonPrettyGeneratorImpl extends JsonGeneratorImpl { + private int indentLevel; + private static final String INDENT = " "; + + public JsonPrettyGeneratorImpl(Writer writer, BufferPool bufferPool) { + super(writer, bufferPool); + } + + public JsonPrettyGeneratorImpl(OutputStream out, BufferPool bufferPool) { + super(out, bufferPool); + } + + public JsonPrettyGeneratorImpl(OutputStream out, Charset encoding, BufferPool bufferPool) { + super(out, encoding, bufferPool); + } + + @Override + public JsonGenerator writeStartObject() { + super.writeStartObject(); + indentLevel++; + return this; + } + + @Override + public JsonGenerator writeStartObject(String name) { + super.writeStartObject(name); + indentLevel++; + return this; + } + + @Override + public JsonGenerator writeStartArray() { + super.writeStartArray(); + indentLevel++; + return this; + } + + @Override + public JsonGenerator writeStartArray(String name) { + super.writeStartArray(name); + indentLevel++; + return this; + } + + @Override + public JsonGenerator writeEnd() { + writeNewLine(); + indentLevel--; + writeIndent(); + super.writeEnd(); + return this; + } + + private void writeIndent() { + for(int i=0; i < indentLevel; i++) { + writeString(INDENT); + } + } + + @Override + protected void writeComma() { + super.writeComma(); + if (isCommaAllowed() && !inNone()) { + writeChar('\n'); + writeIndent(); + } + } + + @Override + protected void writeColon() { + super.writeColon(); + writeChar(' '); + } + + private void writeNewLine() { + writeChar('\n'); + } +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonProviderImpl.java b/impl/src/main/java/org/glassfish/json/JsonProviderImpl.java new file mode 100644 index 0000000..a4ebc8a --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonProviderImpl.java
@@ -0,0 +1,290 @@ +/* + * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; +import org.glassfish.json.api.JsonConfig; + +import jakarta.json.*; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonGeneratorFactory; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParserFactory; +import jakarta.json.spi.JsonProvider; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * @author Jitendra Kotamraju + * @author Kin-man Chung + * @author Alex Soto + */ +public class JsonProviderImpl extends JsonProvider { + private final BufferPool bufferPool = new BufferPoolImpl(); + + @Override + public JsonGenerator createGenerator(Writer writer) { + return new JsonGeneratorImpl(writer, bufferPool); + } + + @Override + public JsonGenerator createGenerator(OutputStream out) { + return new JsonGeneratorImpl(out, bufferPool); + } + + @Override + public JsonParser createParser(Reader reader) { + return new JsonParserImpl(reader, bufferPool); + } + + @Override + public JsonParser createParser(InputStream in) { + return new JsonParserImpl(in, bufferPool); + } + + @Override + public JsonParserFactory createParserFactory(Map<String, ?> config) { + BufferPool pool = null; + if (config != null && config.containsKey(BufferPool.class.getName())) { + pool = (BufferPool)config.get(BufferPool.class.getName()); + } + if (pool == null) { + pool = bufferPool; + } + return new JsonParserFactoryImpl(pool); + } + + @Override + public JsonGeneratorFactory createGeneratorFactory(Map<String, ?> config) { + Map<String, Object> providerConfig; + boolean prettyPrinting; + BufferPool pool; + if (config == null) { + providerConfig = Collections.emptyMap(); + prettyPrinting = false; + pool = bufferPool; + } else { + providerConfig = new HashMap<>(); + if (prettyPrinting=JsonProviderImpl.isPrettyPrintingEnabled(config)) { + providerConfig.put(JsonGenerator.PRETTY_PRINTING, true); + } + pool = (BufferPool)config.get(BufferPool.class.getName()); + if (pool != null) { + providerConfig.put(BufferPool.class.getName(), pool); + } else { + pool = bufferPool; + } + providerConfig = Collections.unmodifiableMap(providerConfig); + } + + return new JsonGeneratorFactoryImpl(providerConfig, prettyPrinting, pool); + } + + @Override + public JsonReader createReader(Reader reader) { + return new JsonReaderImpl(reader, bufferPool); + } + + @Override + public JsonReader createReader(InputStream in) { + return new JsonReaderImpl(in, bufferPool); + } + + @Override + public JsonWriter createWriter(Writer writer) { + return new JsonWriterImpl(writer, bufferPool); + } + + @Override + public JsonWriter createWriter(OutputStream out) { + return new JsonWriterImpl(out, bufferPool); + } + + @Override + public JsonWriterFactory createWriterFactory(Map<String, ?> config) { + Map<String, Object> providerConfig; + boolean prettyPrinting; + BufferPool pool; + if (config == null) { + providerConfig = Collections.emptyMap(); + prettyPrinting = false; + pool = bufferPool; + } else { + providerConfig = new HashMap<>(); + if (prettyPrinting=JsonProviderImpl.isPrettyPrintingEnabled(config)) { + providerConfig.put(JsonGenerator.PRETTY_PRINTING, true); + } + pool = (BufferPool)config.get(BufferPool.class.getName()); + if (pool != null) { + providerConfig.put(BufferPool.class.getName(), pool); + } else { + pool = bufferPool; + } + providerConfig = Collections.unmodifiableMap(providerConfig); + } + return new JsonWriterFactoryImpl(providerConfig, prettyPrinting, pool); + } + + @Override + public JsonReaderFactory createReaderFactory(Map<String, ?> config) { + Map<String, Object> providerConfig; + boolean rejectDuplicateKeys; + BufferPool pool; + if (config == null) { + providerConfig = Collections.emptyMap(); + rejectDuplicateKeys = false; + pool = bufferPool; + } else { + providerConfig = new HashMap<>(); + if (rejectDuplicateKeys = JsonProviderImpl.isRejectDuplicateKeysEnabled(config)) { + providerConfig.put(JsonConfig.REJECT_DUPLICATE_KEYS, true); + } + pool = (BufferPool) config.get(BufferPool.class.getName()); + if (pool != null) { + providerConfig.put(BufferPool.class.getName(), pool); + } else { + pool = bufferPool; + } + providerConfig = Collections.unmodifiableMap(providerConfig); + } + return new JsonReaderFactoryImpl(providerConfig, pool, rejectDuplicateKeys); + } + + @Override + public JsonObjectBuilder createObjectBuilder() { + return new JsonObjectBuilderImpl(bufferPool); + } + + @Override + public JsonObjectBuilder createObjectBuilder(JsonObject object) { + return new JsonObjectBuilderImpl(object, bufferPool); + } + + @Override + public JsonObjectBuilder createObjectBuilder(Map<String, Object> map) { + return new JsonObjectBuilderImpl(map, bufferPool); + } + + @Override + public JsonArrayBuilder createArrayBuilder() { + return new JsonArrayBuilderImpl(bufferPool); + } + + @Override + public JsonArrayBuilder createArrayBuilder(JsonArray array) { + return new JsonArrayBuilderImpl(array, bufferPool); + } + + @Override + public JsonArrayBuilder createArrayBuilder(Collection<?> collection) { + return new JsonArrayBuilderImpl(collection, bufferPool); + } + + @Override + public JsonPointer createPointer(String jsonPointer) { + return new JsonPointerImpl(jsonPointer); + } + + @Override + public JsonPatchBuilder createPatchBuilder() { + return new JsonPatchBuilderImpl(); + } + + @Override + public JsonPatchBuilder createPatchBuilder(JsonArray array) { + return new JsonPatchBuilderImpl(array); + } + + @Override + public JsonPatch createPatch(JsonArray array) { + return new JsonPatchImpl(array); + } + + @Override + public JsonPatch createDiff(JsonStructure source, JsonStructure target) { + return new JsonPatchImpl(JsonPatchImpl.diff(source, target)); + } + + @Override + public JsonMergePatch createMergePatch(JsonValue patch) { + return new JsonMergePatchImpl(patch); + } + + @Override + public JsonMergePatch createMergeDiff(JsonValue source, JsonValue target) { + return new JsonMergePatchImpl(JsonMergePatchImpl.diff(source, target)); + } + + @Override + public JsonString createValue(String value) { + return new JsonStringImpl(value); + } + + @Override + public JsonNumber createValue(int value) { + return JsonNumberImpl.getJsonNumber(value); + } + + @Override + public JsonNumber createValue(long value) { + return JsonNumberImpl.getJsonNumber(value); + } + + @Override + public JsonNumber createValue(double value) { + return JsonNumberImpl.getJsonNumber(value); + } + + @Override + public JsonNumber createValue(BigInteger value) { + return JsonNumberImpl.getJsonNumber(value); + } + + @Override + public JsonNumber createValue(BigDecimal value) { + return JsonNumberImpl.getJsonNumber(value); + } + + @Override + public JsonBuilderFactory createBuilderFactory(Map<String, ?> config) { + BufferPool pool = bufferPool; + boolean rejectDuplicateKeys = false; + if (config != null) { + if (config.containsKey(BufferPool.class.getName())) { + pool = (BufferPool) config.get(BufferPool.class.getName()); + } + rejectDuplicateKeys = JsonProviderImpl.isRejectDuplicateKeysEnabled(config); + } + return new JsonBuilderFactoryImpl(pool, rejectDuplicateKeys); + } + + static boolean isPrettyPrintingEnabled(Map<String, ?> config) { + return config.containsKey(JsonGenerator.PRETTY_PRINTING); + } + + static boolean isRejectDuplicateKeysEnabled(Map<String, ?> config) { + return config.containsKey(JsonConfig.REJECT_DUPLICATE_KEYS); + } +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonReaderFactoryImpl.java b/impl/src/main/java/org/glassfish/json/JsonReaderFactoryImpl.java new file mode 100644 index 0000000..df98252 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonReaderFactoryImpl.java
@@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.JsonReader; +import jakarta.json.JsonReaderFactory; +import java.io.InputStream; +import java.io.Reader; +import java.nio.charset.Charset; +import java.util.Map; + +/** + * @author Jitendra Kotamraju + */ +class JsonReaderFactoryImpl implements JsonReaderFactory { + private final Map<String, ?> config; + private final BufferPool bufferPool; + private final boolean rejectDuplicateKeys; + + JsonReaderFactoryImpl(Map<String, ?> config, BufferPool bufferPool, boolean rejectDuplicateKeys) { + this.config = config; + this.bufferPool = bufferPool; + this.rejectDuplicateKeys = rejectDuplicateKeys; + } + + @Override + public JsonReader createReader(Reader reader) { + return new JsonReaderImpl(reader, bufferPool, rejectDuplicateKeys); + } + + @Override + public JsonReader createReader(InputStream in) { + return new JsonReaderImpl(in, bufferPool, rejectDuplicateKeys); + } + + @Override + public JsonReader createReader(InputStream in, Charset charset) { + return new JsonReaderImpl(in, charset, bufferPool, rejectDuplicateKeys); + } + + @Override + public Map<String, ?> getConfigInUse() { + return config; + } +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonReaderImpl.java b/impl/src/main/java/org/glassfish/json/JsonReaderImpl.java new file mode 100644 index 0000000..967d705 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonReaderImpl.java
@@ -0,0 +1,147 @@ +/* + * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import java.io.InputStream; +import java.io.Reader; +import java.nio.charset.Charset; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; + +/** + * JsonReader impl using parser and builders. + * + * @author Jitendra Kotamraju + */ +class JsonReaderImpl implements JsonReader { + private final JsonParserImpl parser; + private boolean readDone; + private final BufferPool bufferPool; + + JsonReaderImpl(Reader reader, BufferPool bufferPool) { + this(reader, bufferPool, false); + } + + JsonReaderImpl(Reader reader, BufferPool bufferPool, boolean rejectDuplicateKeys) { + parser = new JsonParserImpl(reader, bufferPool, rejectDuplicateKeys); + this.bufferPool = bufferPool; + } + + JsonReaderImpl(InputStream in, BufferPool bufferPool) { + this(in, bufferPool, false); + } + + JsonReaderImpl(InputStream in, BufferPool bufferPool, boolean rejectDuplicateKeys) { + parser = new JsonParserImpl(in, bufferPool, rejectDuplicateKeys); + this.bufferPool = bufferPool; + } + + JsonReaderImpl(InputStream in, Charset charset, BufferPool bufferPool) { + this(in, charset, bufferPool, false); + } + + JsonReaderImpl(InputStream in, Charset charset, BufferPool bufferPool, boolean rejectDuplicateKeys) { + parser = new JsonParserImpl(in, charset, bufferPool, rejectDuplicateKeys); + this.bufferPool = bufferPool; + } + + @Override + public JsonStructure read() { + if (readDone) { + throw new IllegalStateException(JsonMessages.READER_READ_ALREADY_CALLED()); + } + readDone = true; + if (parser.hasNext()) { + try { + JsonParser.Event e = parser.next(); + if (e == JsonParser.Event.START_ARRAY) { + return parser.getArray(); + } else if (e == JsonParser.Event.START_OBJECT) { + return parser.getObject(); + } + } catch (IllegalStateException ise) { + throw new JsonParsingException(ise.getMessage(), ise, parser.getLastCharLocation()); + } + } + throw new JsonException(JsonMessages.INTERNAL_ERROR()); + } + + @Override + public JsonObject readObject() { + if (readDone) { + throw new IllegalStateException(JsonMessages.READER_READ_ALREADY_CALLED()); + } + readDone = true; + if (parser.hasNext()) { + try { + parser.next(); + return parser.getObject(); + } catch (IllegalStateException ise) { + throw new JsonParsingException(ise.getMessage(), ise, parser.getLastCharLocation()); + } + } + throw new JsonException(JsonMessages.INTERNAL_ERROR()); + } + + @Override + public JsonArray readArray() { + if (readDone) { + throw new IllegalStateException(JsonMessages.READER_READ_ALREADY_CALLED()); + } + readDone = true; + if (parser.hasNext()) { + try { + parser.next(); + return parser.getArray(); + } catch (IllegalStateException ise) { + throw new JsonParsingException(ise.getMessage(), ise, parser.getLastCharLocation()); + } + } + throw new JsonException(JsonMessages.INTERNAL_ERROR()); + } + + @Override + public JsonValue readValue() { + if (readDone) { + throw new IllegalStateException(JsonMessages.READER_READ_ALREADY_CALLED()); + } + readDone = true; + if (parser.hasNext()) { + try { + parser.next(); + return parser.getValue(); + } catch (IllegalStateException ise) { + throw new JsonParsingException(ise.getMessage(), ise, parser.getLastCharLocation()); + } + } + throw new JsonException(JsonMessages.INTERNAL_ERROR()); + } + + @Override + public void close() { + readDone = true; + parser.close(); + } +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonStringImpl.java b/impl/src/main/java/org/glassfish/json/JsonStringImpl.java new file mode 100644 index 0000000..ca9fb4f --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonStringImpl.java
@@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.JsonString; + +/** + * JsonString impl + * + * @author Jitendra Kotamraju + */ +final class JsonStringImpl implements JsonString { + + private final String value; + + JsonStringImpl(String value) { + this.value = value; + } + + @Override + public String getString() { + return value; + } + + @Override + public CharSequence getChars() { + return value; + } + + @Override + public ValueType getValueType() { + return ValueType.STRING; + } + + @Override + public int hashCode() { + return getString().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj){ + return true; + } + if (!(obj instanceof JsonString)) { + return false; + } + JsonString other = (JsonString)obj; + return getString().equals(other.getString()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('"'); + + for(int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + // unescaped = %x20-21 | %x23-5B | %x5D-10FFFF + if (c >= 0x20 && c <= 0x10ffff && c != 0x22 && c != 0x5c) { + sb.append(c); + } else { + switch (c) { + case '"': + case '\\': + sb.append('\\'); sb.append(c); + break; + case '\b': + sb.append('\\'); sb.append('b'); + break; + case '\f': + sb.append('\\'); sb.append('f'); + break; + case '\n': + sb.append('\\'); sb.append('n'); + break; + case '\r': + sb.append('\\'); sb.append('r'); + break; + case '\t': + sb.append('\\'); sb.append('t'); + break; + default: + String hex = "000" + Integer.toHexString(c); + sb.append("\\u").append(hex.substring(hex.length() - 4)); + } + } + } + + sb.append('"'); + return sb.toString(); + } +} +
diff --git a/impl/src/main/java/org/glassfish/json/JsonStructureParser.java b/impl/src/main/java/org/glassfish/json/JsonStructureParser.java new file mode 100644 index 0000000..e57dafa --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonStructureParser.java
@@ -0,0 +1,311 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.*; +import jakarta.json.stream.JsonLocation; +import jakarta.json.stream.JsonParser; +import java.math.BigDecimal; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; + +/** + * {@link JsonParser} implementation on top of JsonArray/JsonObject + * + * @author Jitendra Kotamraju + */ +class JsonStructureParser implements JsonParser { + + private Scope current; + private Event state; + private final Deque<Scope> scopeStack = new ArrayDeque<>(); + + JsonStructureParser(JsonArray array) { + current = new ArrayScope(array); + } + + JsonStructureParser(JsonObject object) { + current = new ObjectScope(object); + } + + @Override + public String getString() { + switch (state) { + case KEY_NAME: + return ((ObjectScope)current).key; + case VALUE_STRING: + return ((JsonString)current.getJsonValue()).getString(); + case VALUE_NUMBER: + return ((JsonNumber)current.getJsonValue()).toString(); + default: + throw new IllegalStateException(JsonMessages.PARSER_GETSTRING_ERR(state)); + } + } + + @Override + public boolean isIntegralNumber() { + if (state == Event.VALUE_NUMBER) { + return ((JsonNumber)current.getJsonValue()).isIntegral(); + } + throw new IllegalStateException(JsonMessages.PARSER_ISINTEGRALNUMBER_ERR(state)); + } + + @Override + public int getInt() { + if (state == Event.VALUE_NUMBER) { + return ((JsonNumber)current.getJsonValue()).intValue(); + } + throw new IllegalStateException(JsonMessages.PARSER_GETINT_ERR(state)); + } + + @Override + public long getLong() { + if (state == Event.VALUE_NUMBER) { + return ((JsonNumber)current.getJsonValue()).longValue(); + } + throw new IllegalStateException(JsonMessages.PARSER_GETLONG_ERR(state)); + } + + @Override + public BigDecimal getBigDecimal() { + if (state == Event.VALUE_NUMBER) { + return ((JsonNumber)current.getJsonValue()).bigDecimalValue(); + } + throw new IllegalStateException(JsonMessages.PARSER_GETBIGDECIMAL_ERR(state)); + } + + @Override + public JsonLocation getLocation() { + return JsonLocationImpl.UNKNOWN; + } + + @Override + public boolean hasNext() { + return !((state == Event.END_OBJECT || state == Event.END_ARRAY) && scopeStack.isEmpty()); + } + + @Override + public Event next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + transition(); + return state; + } + + private void transition() { + if (state == null) { + state = current instanceof ArrayScope ? Event.START_ARRAY : Event.START_OBJECT; + } else { + if (state == Event.END_OBJECT || state == Event.END_ARRAY) { + current = scopeStack.pop(); + } + if (current instanceof ArrayScope) { + if (current.hasNext()) { + current.next(); + state = getState(current.getJsonValue()); + if (state == Event.START_ARRAY || state == Event.START_OBJECT) { + scopeStack.push(current); + current = Scope.createScope(current.getJsonValue()); + } + } else { + state = Event.END_ARRAY; + } + } else { + // ObjectScope + if (state == Event.KEY_NAME) { + state = getState(current.getJsonValue()); + if (state == Event.START_ARRAY || state == Event.START_OBJECT) { + scopeStack.push(current); + current = Scope.createScope(current.getJsonValue()); + } + } else { + if (current.hasNext()) { + current.next(); + state = Event.KEY_NAME; + } else { + state = Event.END_OBJECT; + } + } + } + } + } + + @Override + public void close() { + // no-op + } + + @Override + public void skipObject() { + if (current instanceof ObjectScope) { + int depth = 1; + do { + if (state == Event.KEY_NAME) { + state = getState(current.getJsonValue()); + switch (state) { + case START_OBJECT: + depth++; + break; + case END_OBJECT: + depth--; + break; + default: + //no-op + } + } else { + if (current.hasNext()) { + current.next(); + state = Event.KEY_NAME; + } else { + state = Event.END_OBJECT; + depth--; + } + } + } while (state != Event.END_OBJECT && depth > 0); + } + } + + @Override + public void skipArray() { + if (current instanceof ArrayScope) { + int depth = 1; + do { + if (current.hasNext()) { + current.next(); + state = getState(current.getJsonValue()); + switch (state) { + case START_ARRAY: + depth++; + break; + case END_ARRAY: + depth--; + break; + default: + //no-op + } + } else { + state = Event.END_ARRAY; + depth--; + } + } while (!(state == Event.END_ARRAY && depth == 0)); + } + } + + private static Event getState(JsonValue value) { + switch (value.getValueType()) { + case ARRAY: + return Event.START_ARRAY; + case OBJECT: + return Event.START_OBJECT; + case STRING: + return Event.VALUE_STRING; + case NUMBER: + return Event.VALUE_NUMBER; + case TRUE: + return Event.VALUE_TRUE; + case FALSE: + return Event.VALUE_FALSE; + case NULL: + return Event.VALUE_NULL; + default: + throw new JsonException(JsonMessages.PARSER_STATE_ERR(value.getValueType())); + } + } + + private static abstract class Scope implements Iterator { + abstract JsonValue getJsonValue(); + + static Scope createScope(JsonValue value) { + if (value instanceof JsonArray) { + return new ArrayScope((JsonArray)value); + } else if (value instanceof JsonObject) { + return new ObjectScope((JsonObject)value); + } + throw new JsonException(JsonMessages.PARSER_SCOPE_ERR(value)); + } + } + + private static class ArrayScope extends Scope { + private final Iterator<JsonValue> it; + private JsonValue value; + + ArrayScope(JsonArray array) { + this.it = array.iterator(); + } + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public JsonValue next() { + value = it.next(); + return value; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + JsonValue getJsonValue() { + return value; + } + + } + + private static class ObjectScope extends Scope { + private final Iterator<Map.Entry<String, JsonValue>> it; + private JsonValue value; + private String key; + + ObjectScope(JsonObject object) { + this.it = object.entrySet().iterator(); + } + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public Map.Entry<String, JsonValue> next() { + Map.Entry<String, JsonValue> next = it.next(); + this.key = next.getKey(); + this.value = next.getValue(); + return next; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + JsonValue getJsonValue() { + return value; + } + + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonTokenizer.java b/impl/src/main/java/org/glassfish/json/JsonTokenizer.java new file mode 100644 index 0000000..be2b952 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonTokenizer.java
@@ -0,0 +1,586 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.JsonException; +import jakarta.json.stream.JsonLocation; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; +import java.io.*; +import java.math.BigDecimal; +import java.util.Arrays; + +import jakarta.json.stream.JsonParser.Event; + +/** + * JSON Tokenizer + * + * @author Jitendra Kotamraju + */ +final class JsonTokenizer implements Closeable { + // Table to look up hex ch -> value (for e.g HEX['F'] = 15, HEX['5'] = 5) + private final static int[] HEX = new int[128]; + static { + Arrays.fill(HEX, -1); + for (int i='0'; i <= '9'; i++) { + HEX[i] = i-'0'; + } + for (int i='A'; i <= 'F'; i++) { + HEX[i] = 10+i-'A'; + } + for (int i='a'; i <= 'f'; i++) { + HEX[i] = 10+i-'a'; + } + } + private final static int HEX_LENGTH = HEX.length; + + private final BufferPool bufferPool; + + private final Reader reader; + + // Internal buffer that is used for parsing. It is also used + // for storing current string and number value token + private char[] buf; + + // Indexes in buffer + // + // XXXssssssssssssXXXXXXXXXXXXXXXXXXXXXXrrrrrrrrrrrrrrXXXXXX + // ^ ^ ^ ^ + // | | | | + // storeBegin storeEnd readBegin readEnd + private int readBegin; + private int readEnd; + private int storeBegin; + private int storeEnd; + + // line number of the current pointer of parsing char + private long lineNo = 1; + + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + // ^ + // | + // bufferOffset + // + // offset of the last \r\n or \n. will be used to calculate column number + // of a token or an error. This may be outside of the buffer. + private long lastLineOffset = 0; + // offset in the stream for the start of the buffer, will be used in + // calculating JsonLocation's stream offset, column no. + private long bufferOffset = 0; + + private boolean minus; + private boolean fracOrExp; + private BigDecimal bd; + + enum JsonToken { + CURLYOPEN(Event.START_OBJECT, false), + SQUAREOPEN(Event.START_ARRAY, false), + COLON(null, false), + COMMA(null, false), + STRING(Event.VALUE_STRING, true), + NUMBER(Event.VALUE_NUMBER, true), + TRUE(Event.VALUE_TRUE, true), + FALSE(Event.VALUE_FALSE, true), + NULL(Event.VALUE_NULL, true), + CURLYCLOSE(Event.END_OBJECT, false), + SQUARECLOSE(Event.END_ARRAY, false), + EOF(null, false); + + private final JsonParser.Event event; + private final boolean value; + + JsonToken(JsonParser.Event event, boolean value) { + this.event = event; + this.value = value; + } + + JsonParser.Event getEvent() { + return event; + } + + boolean isValue() { + return value; + } + } + + JsonTokenizer(Reader reader, BufferPool bufferPool) { + this.reader = reader; + this.bufferPool = bufferPool; + buf = bufferPool.take(); + } + + private void readString() { + // when inPlace is true, no need to copy chars + boolean inPlace = true; + storeBegin = storeEnd = readBegin; + + do { + // Write unescaped char block within the current buffer + if (inPlace) { + int ch; + while(readBegin < readEnd && ((ch=buf[readBegin]) >= 0x20) && ch != '\\') { + if (ch == '"') { + storeEnd = readBegin++; // ++ to consume quote char + return; // Got the entire string + } + readBegin++; // consume unescaped char + } + storeEnd = readBegin; + } + + // string may be crossing buffer boundaries and may contain + // escaped characters. + int ch = read(); + if (ch >= 0x20 && ch != 0x22 && ch != 0x5c) { + if (!inPlace) { + buf[storeEnd] = (char)ch; + } + storeEnd++; + continue; + } + switch (ch) { + case '\\': + inPlace = false; // Now onwards need to copy chars + unescape(); + break; + case '"': + return; + default: + throw unexpectedChar(ch); + } + } while (true); + } + + private void unescape() { + int ch = read(); + switch (ch) { + case 'b': + buf[storeEnd++] = '\b'; + break; + case 't': + buf[storeEnd++] = '\t'; + break; + case 'n': + buf[storeEnd++] = '\n'; + break; + case 'f': + buf[storeEnd++] = '\f'; + break; + case 'r': + buf[storeEnd++] = '\r'; + break; + case '"': + case '\\': + case '/': + buf[storeEnd++] = (char)ch; + break; + case 'u': { + int unicode = 0; + for (int i = 0; i < 4; i++) { + int ch3 = read(); + int digit = (ch3 >= 0 && ch3 < HEX_LENGTH) ? HEX[ch3] : -1; + if (digit < 0) { + throw unexpectedChar(ch3); + } + unicode = (unicode << 4)|digit; + } + buf[storeEnd++] = (char)unicode; + break; + } + default: + throw unexpectedChar(ch); + } + } + + // Reads a number char. If the char is within the buffer, directly + // reads from the buffer. Otherwise, uses read() which takes care + // of resizing, filling up the buf, adjusting the pointers + private int readNumberChar() { + if (readBegin < readEnd) { + return buf[readBegin++]; + } else { + storeEnd = readBegin; + return read(); + } + } + + private void readNumber(int ch) { + storeBegin = storeEnd = readBegin-1; + // sign + if (ch == '-') { + this.minus = true; + ch = readNumberChar(); + if (ch < '0' || ch >'9') { + throw unexpectedChar(ch); + } + } + + // int + if (ch == '0') { + ch = readNumberChar(); + } else { + do { + ch = readNumberChar(); + } while (ch >= '0' && ch <= '9'); + } + + // frac + if (ch == '.') { + this.fracOrExp = true; + int count = 0; + do { + ch = readNumberChar(); + count++; + } while (ch >= '0' && ch <= '9'); + if (count == 1) { + throw unexpectedChar(ch); + } + } + + // exp + if (ch == 'e' || ch == 'E') { + this.fracOrExp = true; + ch = readNumberChar(); + if (ch == '+' || ch == '-') { + ch = readNumberChar(); + } + int count; + for (count = 0; ch >= '0' && ch <= '9'; count++) { + ch = readNumberChar(); + } + if (count == 0) { + throw unexpectedChar(ch); + } + } + if (ch != -1) { + // Only reset readBegin if eof has not been reached + readBegin--; + storeEnd = readBegin; + } + } + + private void readTrue() { + int ch1 = read(); + if (ch1 != 'r') { + throw expectedChar(ch1, 'r'); + } + int ch2 = read(); + if (ch2 != 'u') { + throw expectedChar(ch2, 'u'); + } + int ch3 = read(); + if (ch3 != 'e') { + throw expectedChar(ch3, 'e'); + } + } + + private void readFalse() { + int ch1 = read(); + if (ch1 != 'a') { + throw expectedChar(ch1, 'a'); + } + int ch2 = read(); + if (ch2 != 'l') { + throw expectedChar(ch2, 'l'); + } + int ch3 = read(); + if (ch3 != 's') { + throw expectedChar(ch3, 's'); + } + int ch4 = read(); + if (ch4 != 'e') { + throw expectedChar(ch4, 'e'); + } + } + + private void readNull() { + int ch1 = read(); + if (ch1 != 'u') { + throw expectedChar(ch1, 'u'); + } + int ch2 = read(); + if (ch2 != 'l') { + throw expectedChar(ch2, 'l'); + } + int ch3 = read(); + if (ch3 != 'l') { + throw expectedChar(ch3, 'l'); + } + } + + /* + * Could be optimized if the parser uses separate methods to match colon + * etc (that would avoid the switch statement cost in certain cases) + */ + JsonToken nextToken() { + reset(); + int ch = read(); + + // whitespace + while (ch == 0x20 || ch == 0x09 || ch == 0x0a || ch == 0x0d) { + if (ch == '\r') { + ++lineNo; + ch = read(); + if (ch == '\n') { + lastLineOffset = bufferOffset+readBegin; + } else { + lastLineOffset = bufferOffset+readBegin-1; + continue; + } + } else if (ch == '\n') { + ++lineNo; + lastLineOffset = bufferOffset+readBegin; + } + ch = read(); + } + + switch (ch) { + case '"': + readString(); + return JsonToken.STRING; + case '{': + return JsonToken.CURLYOPEN; + case '[': + return JsonToken.SQUAREOPEN; + case ':': + return JsonToken.COLON; + case ',': + return JsonToken.COMMA; + case 't': + readTrue(); + return JsonToken.TRUE; + case 'f': + readFalse(); + return JsonToken.FALSE; + case 'n': + readNull(); + return JsonToken.NULL; + case ']': + return JsonToken.SQUARECLOSE; + case '}': + return JsonToken.CURLYCLOSE; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + readNumber(ch); + return JsonToken.NUMBER; + case -1: + return JsonToken.EOF; + default: + throw unexpectedChar(ch); + } + } + + boolean hasNextToken() { + reset(); + int ch = peek(); + + // whitespace + while (ch == 0x20 || ch == 0x09 || ch == 0x0a || ch == 0x0d) { + if (ch == '\r') { + ++lineNo; + ++readBegin; + ch = peek(); + if (ch == '\n') { + lastLineOffset = bufferOffset+readBegin+1; + } else { + lastLineOffset = bufferOffset+readBegin; + continue; + } + } else if (ch == '\n') { + ++lineNo; + lastLineOffset = bufferOffset+readBegin+1; + } + ++readBegin; + ch = peek(); + } + return ch != -1; + } + + private int peek() { + try { + if (readBegin == readEnd) { // need to fill the buffer + int len = fillBuf(); + if (len == -1) { + return -1; + } + assert len != 0; + readBegin = storeEnd; + readEnd = readBegin+len; + } + return buf[readBegin]; + } catch (IOException ioe) { + throw new JsonException(JsonMessages.TOKENIZER_IO_ERR(), ioe); + } + } + + // Gives the location of the last char. Used for + // JsonParsingException.getLocation + JsonLocation getLastCharLocation() { + // Already read the char, so subtracting -1 + return new JsonLocationImpl(lineNo, bufferOffset +readBegin-lastLineOffset, bufferOffset +readBegin-1); + } + + // Gives the parser location. Used for JsonParser.getLocation + JsonLocation getLocation() { + return new JsonLocationImpl(lineNo, bufferOffset +readBegin-lastLineOffset+1, bufferOffset +readBegin); + } + + private int read() { + try { + if (readBegin == readEnd) { // need to fill the buffer + int len = fillBuf(); + if (len == -1) { + return -1; + } + assert len != 0; + readBegin = storeEnd; + readEnd = readBegin+len; + } + return buf[readBegin++]; + } catch (IOException ioe) { + throw new JsonException(JsonMessages.TOKENIZER_IO_ERR(), ioe); + } + } + + private int fillBuf() throws IOException { + if (storeEnd != 0) { + int storeLen = storeEnd-storeBegin; + if (storeLen > 0) { + // there is some store data + if (storeLen == buf.length) { + // buffer is full, double the capacity + char[] doubleBuf = Arrays.copyOf(buf, 2 * buf.length); + bufferPool.recycle(buf); + buf = doubleBuf; + } else { + // Left shift all the stored data to make space + System.arraycopy(buf, storeBegin, buf, 0, storeLen); + storeEnd = storeLen; + storeBegin = 0; + bufferOffset += readBegin-storeEnd; + } + } else { + storeBegin = storeEnd = 0; + bufferOffset += readBegin; + } + } else { + bufferOffset += readBegin; + } + // Fill the rest of the buf + return reader.read(buf, storeEnd, buf.length-storeEnd); + } + + // state associated with the current token is no more valid + private void reset() { + if (storeEnd != 0) { + storeBegin = 0; + storeEnd = 0; + bd = null; + minus = false; + fracOrExp = false; + } + } + + String getValue() { + return new String(buf, storeBegin, storeEnd-storeBegin); + } + + BigDecimal getBigDecimal() { + if (bd == null) { + bd = new BigDecimal(buf, storeBegin, storeEnd-storeBegin); + } + return bd; + } + + int getInt() { + // no need to create BigDecimal for common integer values (1-9 digits) + int storeLen = storeEnd-storeBegin; + if (!fracOrExp && (storeLen <= 9 || (minus && storeLen <= 10))) { + int num = 0; + int i = minus ? 1 : 0; + for(; i < storeLen; i++) { + num = num * 10 + (buf[storeBegin+i] - '0'); + } + return minus ? -num : num; + } else { + return getBigDecimal().intValue(); + } + } + + long getLong() { + // no need to create BigDecimal for common integer values (1-18 digits) + int storeLen = storeEnd-storeBegin; + if (!fracOrExp && (storeLen <= 18 || (minus && storeLen <= 19))) { + long num = 0; + int i = minus ? 1 : 0; + for(; i < storeLen; i++) { + num = num * 10 + (buf[storeBegin+i] - '0'); + } + return minus ? -num : num; + } else { + return getBigDecimal().longValue(); + } + } + + // returns true for common integer values (1-9 digits). + // So there are cases it will return false even though the number is int + boolean isDefinitelyInt() { + int storeLen = storeEnd-storeBegin; + return !fracOrExp && (storeLen <= 9 || (minus && storeLen <= 10)); + } + + // returns true for common long values (1-18 digits). + // So there are cases it will return false even though the number is long + boolean isDefinitelyLong() { + int storeLen = storeEnd-storeBegin; + return !fracOrExp && (storeLen <= 18 || (minus && storeLen <= 19)); + } + + boolean isIntegral() { + return !fracOrExp || getBigDecimal().scale() == 0; + } + + @Override + public void close() throws IOException { + reader.close(); + bufferPool.recycle(buf); + } + + private JsonParsingException unexpectedChar(int ch) { + JsonLocation location = getLastCharLocation(); + return new JsonParsingException( + JsonMessages.TOKENIZER_UNEXPECTED_CHAR(ch, location), location); + } + + private JsonParsingException expectedChar(int unexpected, char expected) { + JsonLocation location = getLastCharLocation(); + return new JsonParsingException( + JsonMessages.TOKENIZER_EXPECTED_CHAR(unexpected, location, expected), location); + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonUtil.java b/impl/src/main/java/org/glassfish/json/JsonUtil.java new file mode 100644 index 0000000..f971522 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonUtil.java
@@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import java.io.StringReader; +import jakarta.json.JsonReader; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonParsingException; +import org.glassfish.json.api.BufferPool; + +/** + * A utility class + * + * @since 1.1 + */ +public final class JsonUtil { + + private static BufferPool internalPool; + + private JsonUtil() { + } + + static BufferPool getInternalBufferPool() { + if (internalPool == null) { + internalPool = new BufferPoolImpl(); + } + return internalPool; + } + + /** + * Reads the input JSON text and returns a JsonValue. + * <p>For convenience, single quotes as well as double quotes + * are allowed to delimit JSON strings. If single quotes are + * used, any quotes, single or double, in the JSON string must be + * escaped (prepend with a '\'). + * + * @param jsonString the input JSON data + * @return the object model for {@code jsonString} + * @throws JsonParsingException if the input is not legal JSON text + */ + public static JsonValue toJson(String jsonString) { + StringBuilder builder = new StringBuilder(); + boolean single_context = false; + for (int i = 0; i < jsonString.length(); i++) { + char ch = jsonString.charAt(i); + if (ch == '\\') { + i = i + 1; + if (i < jsonString.length()) { + ch = jsonString.charAt(i); + if (!(single_context && ch == '\'')) { + // unescape ' inside single quotes + builder.append('\\'); + } + } + } else if (ch == '\'') { + // Turn ' into ", for proper JSON string + ch = '"'; + single_context = ! single_context; + } + builder.append(ch); + } + + JsonReader reader = new JsonReaderImpl( + new StringReader(builder.toString()), + getInternalBufferPool()); + JsonValue value = reader.readValue(); + reader.close(); + return value; + } +} +
diff --git a/impl/src/main/java/org/glassfish/json/JsonWriterFactoryImpl.java b/impl/src/main/java/org/glassfish/json/JsonWriterFactoryImpl.java new file mode 100644 index 0000000..b1482f8 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonWriterFactoryImpl.java
@@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.JsonWriter; +import jakarta.json.JsonWriterFactory; +import java.io.OutputStream; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.Map; + +/** + * @author Jitendra Kotamraju + */ +class JsonWriterFactoryImpl implements JsonWriterFactory { + private final Map<String, ?> config; // unmodifiable map + private final boolean prettyPrinting; + private final BufferPool bufferPool; + + JsonWriterFactoryImpl(Map<String, ?> config, boolean prettyPrinting, + BufferPool bufferPool) { + this.config = config; + this.prettyPrinting = prettyPrinting; + this.bufferPool = bufferPool; + } + + @Override + public JsonWriter createWriter(Writer writer) { + return new JsonWriterImpl(writer, prettyPrinting, bufferPool); + } + + @Override + public JsonWriter createWriter(OutputStream out) { + return new JsonWriterImpl(out, prettyPrinting, bufferPool); + } + + @Override + public JsonWriter createWriter(OutputStream out, Charset charset) { + return new JsonWriterImpl(out, charset, prettyPrinting, bufferPool); + } + + @Override + public Map<String, ?> getConfigInUse() { + return config; + } +}
diff --git a/impl/src/main/java/org/glassfish/json/JsonWriterImpl.java b/impl/src/main/java/org/glassfish/json/JsonWriterImpl.java new file mode 100644 index 0000000..d7cf86d --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/JsonWriterImpl.java
@@ -0,0 +1,167 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.*; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + * JsonWriter impl using generator. + * + * @author Jitendra Kotamraju + */ +class JsonWriterImpl implements JsonWriter { + + private final JsonGeneratorImpl generator; + private boolean writeDone; + private final NoFlushOutputStream os; + + JsonWriterImpl(Writer writer, BufferPool bufferPool) { + this(writer, false, bufferPool); + } + + JsonWriterImpl(Writer writer, boolean prettyPrinting, BufferPool bufferPool) { + generator = prettyPrinting + ? new JsonPrettyGeneratorImpl(writer, bufferPool) + : new JsonGeneratorImpl(writer, bufferPool); + os = null; + } + + JsonWriterImpl(OutputStream out, BufferPool bufferPool) { + this(out, StandardCharsets.UTF_8, false, bufferPool); + } + + JsonWriterImpl(OutputStream out, boolean prettyPrinting, BufferPool bufferPool) { + this(out, StandardCharsets.UTF_8, prettyPrinting, bufferPool); + } + + JsonWriterImpl(OutputStream out, Charset charset, + boolean prettyPrinting, BufferPool bufferPool) { + // Decorating the given stream, so that buffered contents can be + // written without actually flushing the stream. + this.os = new NoFlushOutputStream(out); + generator = prettyPrinting + ? new JsonPrettyGeneratorImpl(os, charset, bufferPool) + : new JsonGeneratorImpl(os, charset, bufferPool); + } + + @Override + public void writeArray(JsonArray array) { + if (writeDone) { + throw new IllegalStateException(JsonMessages.WRITER_WRITE_ALREADY_CALLED()); + } + writeDone = true; + generator.writeStartArray(); + for(JsonValue value : array) { + generator.write(value); + } + generator.writeEnd(); + // Flush the generator's buffered contents. This won't work for byte + // streams as intermediary OutputStreamWriter buffers. + generator.flushBuffer(); + // Flush buffered contents but not the byte stream. generator.flush() + // does OutputStreamWriter#flushBuffer (package private) and underlying + // byte stream#flush(). Here underlying stream's flush() is no-op. + if (os != null) { + generator.flush(); + } + } + + @Override + public void writeObject(JsonObject object) { + if (writeDone) { + throw new IllegalStateException(JsonMessages.WRITER_WRITE_ALREADY_CALLED()); + } + writeDone = true; + generator.writeStartObject(); + for(Map.Entry<String, JsonValue> e : object.entrySet()) { + generator.write(e.getKey(), e.getValue()); + } + generator.writeEnd(); + // Flush the generator's buffered contents. This won't work for byte + // streams as intermediary OutputStreamWriter buffers. + generator.flushBuffer(); + // Flush buffered contents but not the byte stream. generator.flush() + // does OutputStreamWriter#flushBuffer (package private) and underlying + // byte stream#flush(). Here underlying stream's flush() is no-op. + if (os != null) { + generator.flush(); + } + } + + @Override + public void write(JsonStructure value) { + if (value instanceof JsonArray) { + writeArray((JsonArray)value); + } else { + writeObject((JsonObject)value); + } + } + + @Override + public void write(JsonValue value) { + switch (value.getValueType()) { + case OBJECT: + writeObject((JsonObject) value); + return; + case ARRAY: + writeArray((JsonArray) value); + return; + default: + if (writeDone) { + throw new IllegalStateException(JsonMessages.WRITER_WRITE_ALREADY_CALLED()); + } + writeDone = true; + generator.write(value); + generator.flushBuffer(); + if (os != null) { + generator.flush(); + } + } + } + + @Override + public void close() { + writeDone = true; + generator.close(); + } + + private static final class NoFlushOutputStream extends FilterOutputStream { + public NoFlushOutputStream(OutputStream out) { + super(out); + } + + @Override + public void write(byte b[], int off, int len) throws IOException { + out.write(b, off ,len); + } + + @Override + public void flush() { + // no-op + } + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/MapUtil.java b/impl/src/main/java/org/glassfish/json/MapUtil.java new file mode 100644 index 0000000..b28a1ff --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/MapUtil.java
@@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import org.glassfish.json.api.BufferPool; + +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Collection; +import java.util.Map; + +/** + * Util for transforming a Map to a Json objects. + * + * @author asotobu + */ +public final class MapUtil { + + private MapUtil() { + super(); + } + + static JsonValue handle(Object value, BufferPool bufferPool) { + if (value == null) { + return JsonValue.NULL; + } else if (value instanceof JsonValue) { + return (JsonValue) value; + } else if (value instanceof JsonArrayBuilder) { + return ((JsonArrayBuilder) value).build(); + } else if (value instanceof JsonObjectBuilder) { + return ((JsonObjectBuilder) value).build(); + } else if (value instanceof BigDecimal) { + return JsonNumberImpl.getJsonNumber((BigDecimal) value); + } else if (value instanceof BigInteger) { + return JsonNumberImpl.getJsonNumber((BigInteger) value); + } else if (value instanceof Boolean) { + Boolean b = (Boolean) value; + return b ? JsonValue.TRUE : JsonValue.FALSE; + } else if (value instanceof Double) { + return JsonNumberImpl.getJsonNumber((Double) value); + } else if (value instanceof Integer) { + return JsonNumberImpl.getJsonNumber((Integer) value); + } else if (value instanceof Long) { + return JsonNumberImpl.getJsonNumber((Long) value); + } else if (value instanceof String) { + return new JsonStringImpl((String) value); + } else if (value instanceof Collection) { + @SuppressWarnings("unchecked") + Collection<?> collection = (Collection<?>) value; + JsonArrayBuilder jsonArrayBuilder = new JsonArrayBuilderImpl(collection, bufferPool); + return jsonArrayBuilder.build(); + } else if (value instanceof Map) { + @SuppressWarnings("unchecked") + JsonObjectBuilder object = new JsonObjectBuilderImpl((Map<String, Object>) value, bufferPool); + return object.build(); + } + + throw new IllegalArgumentException(String.format("Type %s is not supported.", value.getClass())); + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/NodeReference.java b/impl/src/main/java/org/glassfish/json/NodeReference.java new file mode 100644 index 0000000..255dbd0 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/NodeReference.java
@@ -0,0 +1,282 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; + +/** + * This class is a helper class for JsonPointer implementation, + * and is not part of the API. + * + * This class encapsulates a reference to a JSON node. + * There are three types of references. + * <ol><li>a reference to the root of a JSON tree.</li> + * <li>a reference to a name/value (possibly non-existing) pair of a JSON object, identified by a name.</li> + * <li>a reference to a member value of a JSON array, identified by an index.</li> + * </ol> + * Static factory methods are provided for creating these references. + * + * <p>A referenced value can be retrieved or replaced. + * The value of a JSON object or JSON array can be + * removed. A new value can be added to a JSON object or + * inserted into a JSON array</p> + * + * <p>Since a {@code JsonObject} or {@code JsonArray} is immutable, these operations + * must not modify the referenced JSON object or array. The methods {@link #add}, + * {@link #replace}, and {@link #remove} returns a new + * JSON object or array after the execution of the operation.</p> + */ +abstract class NodeReference { + + /** + * Return {@code true} if a reference points to a valid value, {@code false} otherwise. + * + * @return {@code true} if a reference points to a value + */ + abstract public boolean contains(); + + /** + * Get the value at the referenced location. + * + * @return the JSON value referenced + * @throws JsonException if the referenced value does not exist + */ + abstract public JsonValue get(); + + /** + * Add or replace a value at the referenced location. + * If the reference is the root of a JSON tree, the added value must be + * a JSON object or array, which becomes the referenced JSON value. + * If the reference is an index of a JSON array, the value is inserted + * into the array at the index. If the index is -1, the value is + * appended to the array. + * If the reference is a name of a JSON object, the name/value pair is added + * to the object, replacing any pair with the same name. + * + * @param value the value to be added + * @return the JsonStructure after the operation + * @throws JsonException if the index to the array is not -1 or is out of range + */ + abstract public JsonStructure add(JsonValue value); + + /** + * Remove the name/value pair from the JSON object, or the value in a JSON array, as specified by the reference + * + * @return the JsonStructure after the operation + * @throws JsonException if the name/value pair of the referenced JSON object + * does not exist, or if the index of the referenced JSON array is + * out of range, or if the reference is a root reference + */ + abstract public JsonStructure remove(); + + /** + * Replace the referenced value with the specified value. + * + * @param value the JSON value to be stored at the referenced location + * @return the JsonStructure after the operation + * @throws JsonException if the name/value pair of the referenced JSON object + * does not exist, or if the index of the referenced JSON array is + * out of range, or if the reference is a root reference + */ + abstract public JsonStructure replace(JsonValue value); + + /** + * Returns a {@code NodeReference} for a {@code JsonStructure}. + * + * @param structure the {@code JsonStructure} referenced + * @return the {@code NodeReference} + */ + public static NodeReference of(JsonStructure structure) { + return new RootReference(structure); + } + + /** + * Returns a {@code NodeReference} for a name/value pair in a + * JSON object. + * + * @param object the referenced JSON object + * @param name the name of the name/pair + * @return the {@code NodeReference} + */ + public static NodeReference of(JsonObject object, String name) { + return new ObjectReference(object, name); + } + + /** + * Returns a {@code NodeReference} for a member value in a + * JSON array. + * + * @param array the referenced JSON array + * @param index the index of the member value in the JSON array + * @return the {@code NodeReference} + */ + public static NodeReference of(JsonArray array, int index) { + return new ArrayReference(array, index); + } + + static class RootReference extends NodeReference { + + private JsonStructure root; + + RootReference(JsonStructure root) { + this.root = root; + } + + @Override + public boolean contains() { + return root != null; + } + + @Override + public JsonValue get() { + return root; + } + + @Override + public JsonStructure add(JsonValue value) { + switch (value.getValueType() ) { + case OBJECT: + case ARRAY: + this.root = (JsonStructure) value; + break; + default: + throw new JsonException(JsonMessages.NODEREF_VALUE_ADD_ERR()); + } + return root; + } + + @Override + public JsonStructure remove() { + throw new JsonException(JsonMessages.NODEREF_VALUE_CANNOT_REMOVE()); + } + + @Override + public JsonStructure replace(JsonValue value) { + return add(value); + } + } + + static class ObjectReference extends NodeReference { + + private final JsonObject object; + private final String key; + + ObjectReference(JsonObject object, String key) { + this.object = object; + this.key = key; + } + + @Override + public boolean contains() { + return object != null && object.containsKey(key); + } + + @Override + public JsonValue get() { + if (!contains()) { + throw new JsonException(JsonMessages.NODEREF_OBJECT_MISSING(key)); + } + return object.get(key); + } + + @Override + public JsonObject add(JsonValue value) { + return new JsonObjectBuilderImpl(object, JsonUtil.getInternalBufferPool()).add(key, value).build(); + } + + @Override + public JsonObject remove() { + if (!contains()) { + throw new JsonException(JsonMessages.NODEREF_OBJECT_MISSING(key)); + } + return new JsonObjectBuilderImpl(object, JsonUtil.getInternalBufferPool()).remove(key).build(); + } + + @Override + public JsonObject replace(JsonValue value) { + if (!contains()) { + throw new JsonException(JsonMessages.NODEREF_OBJECT_MISSING(key)); + } + return add(value); + } + } + + static class ArrayReference extends NodeReference { + + private final JsonArray array; + private final int index; // -1 means "-" in JSON Pointer + + ArrayReference(JsonArray array, int index) { + this.array = array; + this.index = index; + } + + @Override + public boolean contains() { + return array != null && index > -1 && index < array.size(); + } + + @Override + public JsonValue get() { + if (!contains()) { + throw new JsonException(JsonMessages.NODEREF_ARRAY_INDEX_ERR(index, array.size())); + } + return array.get(index); + } + + @Override + public JsonArray add(JsonValue value) { + //TODO should we check for arrayoutofbounds? + // The spec seems to say index = array.size() is allowed. This is handled as append + JsonArrayBuilder builder = new JsonArrayBuilderImpl(this.array, JsonUtil.getInternalBufferPool()); + if (index == -1 || index == array.size()) { + builder.add(value); + } else { + if(index < array.size()) { + builder.add(index, value); + } else { + throw new JsonException(JsonMessages.NODEREF_ARRAY_INDEX_ERR(index, array.size())); + } + } + return builder.build(); + } + + @Override + public JsonArray remove() { + if (!contains()) { + throw new JsonException(JsonMessages.NODEREF_ARRAY_INDEX_ERR(index, array.size())); + } + JsonArrayBuilder builder = new JsonArrayBuilderImpl(this.array, JsonUtil.getInternalBufferPool()); + return builder.remove(index).build(); + } + + @Override + public JsonArray replace(JsonValue value) { + if (!contains()) { + throw new JsonException(JsonMessages.NODEREF_ARRAY_INDEX_ERR(index, array.size())); + } + JsonArrayBuilder builder = new JsonArrayBuilderImpl(this.array, JsonUtil.getInternalBufferPool()); + return builder.set(index, value).build(); + } + } +} +
diff --git a/impl/src/main/java/org/glassfish/json/UnicodeDetectingInputStream.java b/impl/src/main/java/org/glassfish/json/UnicodeDetectingInputStream.java new file mode 100644 index 0000000..d40d45e --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/UnicodeDetectingInputStream.java
@@ -0,0 +1,164 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json; + +import jakarta.json.JsonException; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * A filter stream that detects the unicode encoding for the original + * stream + * + * @author Jitendra Kotamraju + */ +class UnicodeDetectingInputStream extends FilterInputStream { + + private static final Charset UTF_32LE = Charset.forName("UTF-32LE"); + private static final Charset UTF_32BE = Charset.forName("UTF-32BE"); + + private static final byte FF = (byte)0xFF; + private static final byte FE = (byte)0xFE; + private static final byte EF = (byte)0xEF; + private static final byte BB = (byte)0xBB; + private static final byte BF = (byte)0xBF; + private static final byte NUL = (byte)0x00; + + private final byte[] buf = new byte[4]; + private int bufLen; + private int curIndex; + private final Charset charset; + + UnicodeDetectingInputStream(InputStream is) { + super(is); + charset = detectEncoding(); + } + + Charset getCharset() { + return charset; + } + + private void fillBuf() { + int b1; + int b2; + int b3; + int b4; + + try { + b1 = in.read(); + if (b1 == -1) { + return; + } + + b2 = in.read(); + if (b2 == -1) { + bufLen = 1; + buf[0] = (byte)b1; + return; + } + + b3 = in.read(); + if (b3 == -1) { + bufLen = 2; + buf[0] = (byte)b1; + buf[1] = (byte)b2; + return; + } + + b4 = in.read(); + if (b4 == -1) { + bufLen = 3; + buf[0] = (byte)b1; + buf[1] = (byte)b2; + buf[2] = (byte)b3; + return; + } + bufLen = 4; + buf[0] = (byte)b1; + buf[1] = (byte)b2; + buf[2] = (byte)b3; + buf[3] = (byte)b4; + } catch (IOException ioe) { + throw new JsonException(JsonMessages.PARSER_INPUT_ENC_DETECT_IOERR(), ioe); + } + } + + private Charset detectEncoding() { + fillBuf(); + if (bufLen < 2) { + throw new JsonException(JsonMessages.PARSER_INPUT_ENC_DETECT_FAILED()); + } else if (bufLen == 4) { + // Use BOM to detect encoding + if (buf[0] == NUL && buf[1] == NUL && buf[2] == FE && buf[3] == FF) { + curIndex = 4; + return UTF_32BE; + } else if (buf[0] == FF && buf[1] == FE && buf[2] == NUL && buf[3] == NUL) { + curIndex = 4; + return UTF_32LE; + } else if (buf[0] == FE && buf[1] == FF) { + curIndex = 2; + return StandardCharsets.UTF_16BE; + } else if (buf[0] == FF && buf[1] == FE) { + curIndex = 2; + return StandardCharsets.UTF_16LE; + } else if (buf[0] == EF && buf[1] == BB && buf[2] == BF) { + curIndex = 3; + return StandardCharsets.UTF_8; + } + // No BOM, just use JSON RFC's encoding algo to auto-detect + if (buf[0] == NUL && buf[1] == NUL && buf[2] == NUL) { + return UTF_32BE; + } else if (buf[0] == NUL && buf[2] == NUL) { + return StandardCharsets.UTF_16BE; + } else if (buf[1] == NUL && buf[2] == NUL && buf[3] == NUL) { + return UTF_32LE; + } else if (buf[1] == NUL && buf[3] == NUL) { + return StandardCharsets.UTF_16LE; + } + } + return StandardCharsets.UTF_8; + } + + @Override + public int read() throws IOException { + if (curIndex < bufLen) { + return buf[curIndex++]; + } + return in.read(); + } + + @Override + public int read(byte b[], int off, int len) throws IOException { + if (curIndex < bufLen) { + if (len == 0) { + return 0; + } + if (off < 0 || len < 0 || len > b.length -off) { + throw new IndexOutOfBoundsException(); + } + int min = Math.min(bufLen-curIndex, len); + System.arraycopy(buf, curIndex, b, off, min); + curIndex += min; + return min; + } + return in.read(b, off, len); + } + +}
diff --git a/impl/src/main/java/org/glassfish/json/api/BufferPool.java b/impl/src/main/java/org/glassfish/json/api/BufferPool.java new file mode 100644 index 0000000..1141ff0 --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/api/BufferPool.java
@@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.api; + +/** + * char[] pool that pool instances of char[] which are expensive to create. + * + * @author Jitendra Kotamraju + */ +public interface BufferPool { + + /** + * Gets a new char[] object from the pool. + * + * <p> + * If no object is available in the pool, this method creates a new one. + * + * @return + * always non-null. + */ + char[] take(); + + /** + * Returns an object back to the pool. + * + * @param buf object to return back to the pool + */ + void recycle(char[] buf); + +}
diff --git a/impl/src/main/java/org/glassfish/json/api/JsonConfig.java b/impl/src/main/java/org/glassfish/json/api/JsonConfig.java new file mode 100644 index 0000000..f7a160f --- /dev/null +++ b/impl/src/main/java/org/glassfish/json/api/JsonConfig.java
@@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.api; + +public interface JsonConfig { + /** + * Configuration property to reject duplicate keys. The value of the property could be + * be anything. + */ + String REJECT_DUPLICATE_KEYS = "org.glassfish.json.rejectDuplicateKeys"; +}
diff --git a/impl/src/main/javadoc/doc-files/speclicense.html b/impl/src/main/javadoc/doc-files/speclicense.html new file mode 100644 index 0000000..ba29e5e --- /dev/null +++ b/impl/src/main/javadoc/doc-files/speclicense.html
@@ -0,0 +1,72 @@ +<html> +<head> +<title>Eclipse Foundation Specification License - v1.0</title> +</head> +<body> +<h1>Eclipse Foundation Specification License - v1.0</h1> +<p>By using and/or copying this document, or the Eclipse Foundation + document from which this statement is linked, you (the licensee) agree + that you have read, understood, and will comply with the following + terms and conditions:</p> + +<p>Permission to copy, and distribute the contents of this document, or + the Eclipse Foundation document from which this statement is linked, in + any medium for any purpose and without fee or royalty is hereby + granted, provided that you include the following on ALL copies of the + document, or portions thereof, that you use:</p> + +<ul> + <li> link or URL to the original Eclipse Foundation document.</li> + <li>All existing copyright notices, or if one does not exist, a notice + (hypertext is preferred, but a textual representation is permitted) + of the form: "Copyright © [$date-of-document] + “Eclipse Foundation, Inc. <<url to this license>> + " + </li> +</ul> + +<p>Inclusion of the full text of this NOTICE must be provided. We + request that authorship attribution be provided in any software, + documents, or other items or products that you create pursuant to the + implementation of the contents of this document, or any portion + thereof.</p> + +<p>No right to create modifications or derivatives of Eclipse Foundation + documents is granted pursuant to this license, except anyone may + prepare and distribute derivative works and portions of this document + in software that implements the specification, in supporting materials + accompanying such software, and in documentation of such software, + PROVIDED that all such works include the notice below. HOWEVER, the + publication of derivative works of this document for use as a technical + specification is expressly prohibited.</p> + +<p>The notice is:</p> + +<p>"Copyright © 2018 Eclipse Foundation. This software or + document includes material copied from or derived from [title and URI + of the Eclipse Foundation specification document]."</p> + +<h2>Disclaimers</h2> + +<p>THIS DOCUMENT IS PROVIDED "AS IS," AND THE COPYRIGHT + HOLDERS AND THE ECLIPSE FOUNDATION MAKE NO REPRESENTATIONS OR + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, + NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE + SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS + WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR + OTHER RIGHTS.</p> + +<p>THE COPYRIGHT HOLDERS AND THE ECLIPSE FOUNDATION WILL NOT BE LIABLE + FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT + OF ANY USE OF THE DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE + CONTENTS THEREOF.</p> + +<p>The name and trademarks of the copyright holders or the Eclipse + Foundation may NOT be used in advertising or publicity pertaining to + this document or its contents without specific, written prior + permission. Title to copyright in this document will at all times + remain with copyright holders.</p> + +</body> +</html>
diff --git a/impl/src/main/javadoc/overview.html b/impl/src/main/javadoc/overview.html new file mode 100644 index 0000000..2b82208 --- /dev/null +++ b/impl/src/main/javadoc/overview.html
@@ -0,0 +1,108 @@ +<html> +<!-- + + Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<body> +Jakarta JSON Processing provides portable APIs to parse, +generate, transform, and query <a href="http://json.org/">JSON</a> using the +streaming API or the object model API. + +<p>The Streaming API provides a way to parsing and generation of JSON in a +streaming fashion. It hands over parsing and generation control to the +programmer. The streaming API provides an event-based parser and allows an +application developer to ask for the next event rather than handling the event +in a callback. This gives a developer more procedural control over +the processing of the JSON. Application code can process or discard +the parser event, and ask for the next event(pull the event). The +streaming model is adequate for local processing where random access of other +parts of the data is not required. Similarly, the streaming API provides +a way to generate well-formed JSON to a stream by writing one event at a time. + +<p>The object model API creates a random access tree-like structure that +represents the JSON data in memory. The tree can then be navigated and +queried. This programming model is the most flexible and enables processing +that requires random access to the complete contents of the tree. However, +it is often not as efficient as the streaming model and requires more memory. +The object model generates JSON output by navigating the entire tree at once. + +<h1>The Streaming API</h1> +<p>The streaming API is similar to the StAX API for XML and consists of the +interfaces {@link jakarta.json.stream.JsonParser} and +{@link jakarta.json.stream.JsonGenerator}. {@code JsonParser} +contains methods to parse JSON data using the streaming model. +{@code JsonGenerator} contains methods to write JSON data to an ouptut source. + +<p>{@code JsonParser} provides forward, read-only access to +JSON data using the pull parsing programming model. In this model the +application code controls the thread and calls methods in the parser interface +to move the parser forward or to obtain JSON data from the current state of +the parser. Refer to +<a href="jakarta.json/jakarta/json/stream/JsonParser.html#JsonParserExample2">this example</a> +for more details. + +<p>{@code JsonGenerator} provides methods to write JSON to a stream. The +generator writes name/value pairs in JSON objects and values in JSON arrays. +Refer to +<a href="jakarta.json/jakarta/json/stream/JsonGenerator.html#JsonGeneratorExample3">this +example</a> for more details. + +<p>The streaming API is a low-level API designed to process large amounts of +JSON data efficiently. Other JSON frameworks (such as JSON binding) can be +implemented using this API.</p> + +<h1>The Object Model API</h1> +<p>The object model API is similar to the DOM API for XML. It is a high-level +API that provides immutable object models for JSON object and array structures. +These JSON structures are represented as object models using the Java types +{@link jakarta.json.JsonObject} and {@link jakarta.json.JsonArray}. +{@code JsonObject} provides a {@link java.util.Map} view to access the unordered +collection of zero or more name/value pairs from the model. Similarly, +{@code JsonArray} provides a {@link java.util.List} view to access the ordered +sequence of zero or more values from the model. + +<p>The object model API uses builder patterns to create these object models. +Application code can use the interface {@link jakarta.json.JsonObjectBuilder} +to create models that represent JSON objects. The resulting model is of type +{@code JsonObject}. Refer to +<a href="jakarta.json/jakarta/json/JsonObjectBuilder.html#JsonObjectBuilderExample1">this example</a> +for more details. Application code can use the interface +{@link jakarta.json.JsonArrayBuilder} to create models that represent JSON arrays. +The resulting model is of type {@code JsonArray}. Refer to +<a href="jakarta.json/jakarta/json/JsonArrayBuilder.html#JsonArrayBuilderExample1">this example</a> +for more details. + +<p>These object models can also be created from an input source (such as +{@link java.io.InputStream} or {@link java.io.Reader}) using the interface +{@link jakarta.json.JsonReader}. +<a href="jakarta.json/jakarta/json/JsonReader.html#JsonReaderExample1">This example</a> shows +how to read and create an empty {@code JsonArray} model using the interface +{@code JsonReader}. Similarly, these object models can be written to an output +source (such as {@link java.io.OutputStream} or {@link java.io.Writer}) using +the class {@link jakarta.json.JsonWriter}. +<a href="jakarta.json/jakarta/json/JsonWriter.html#JsonWriterExample1">This example</a> shows +how to write an empty {@code JsonObject} model using the interface +{@code JsonWriter}. + +<h1>JSON Pointer, JSON Patch, and JSON Merge Patch</h1> +Jakarta JSON Processing supports the latest standard on +<a href="http://tools.ietf.org/html/rfc6901">JSON Pointer</a>, +<a Href="http://tools.ietf.org/html/rfc6902">JSON Patch</a>, and +<a Href="http://tools.ietf.org/html/rfc7396">JSON Merge Patch</a>. + +</body> +</html>
diff --git a/impl/src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider b/impl/src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider new file mode 100644 index 0000000..52f1a6b --- /dev/null +++ b/impl/src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider
@@ -0,0 +1 @@ +org.glassfish.json.JsonProviderImpl
diff --git a/impl/src/main/resources/org/glassfish/json/messages.properties b/impl/src/main/resources/org/glassfish/json/messages.properties new file mode 100644 index 0000000..1c69310 --- /dev/null +++ b/impl/src/main/resources/org/glassfish/json/messages.properties
@@ -0,0 +1,92 @@ +# +# Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0, which is available at +# http://www.eclipse.org/legal/epl-2.0. +# +# This Source Code may also be made available under the following Secondary +# Licenses when the conditions for such availability set forth in the +# Eclipse Public License v. 2.0 are satisfied: GNU General Public License, +# version 2 with the GNU Classpath Exception, which is available at +# https://www.gnu.org/software/classpath/license.html. +# +# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +# + + + +internal.error=Internal Error + +parser.getString.err=JsonParser#getString() is valid only for KEY_NAME, VALUE_STRING, VALUE_NUMBER parser states. \ + But current parser state is {0} +parser.isIntegralNumber.err=JsonParser#isIntegralNumber() is valid only for VALUE_NUMBER parser state. \ + But current parser state is {0} +parser.getInt.err=JsonParser#getInt() is valid only for VALUE_NUMBER parser state. \ + But current parser state is {0} +parser.getLong.err=JsonParser#getLong() is valid only for VALUE_NUMBER parser state. \ + But current parser state is {0} +parser.getBigDecimal.err=JsonParser#getBigDecimal() is valid only for VALUE_NUMBER parser state. \ + But current parser state is {0} +parser.getArray.err=JsonParser#getArray() or JsonParser#getArrayStream() is valid only for START_ARRAY parser state. \ + But current parser state is {0} +parser.getObject.err=JsonParser#getObject() or JsonParser#getObjectStream() is valid only for START_OBJECT parser state. \ + But current parser state is {0} +parser.getValue.err=JsonParser#getValue() is valid only for START_ARRAY, START_OBJECT, KEY_NAME, VALUE_STRING, VALUE_NUMBER, VALUE_NULL, VALUE_FALSE, VALUE_TRUE parser states. \ + But current parser state is {0} +parser.getValueStream.err=JsonParser#getValueStream() the parser must not be in an array or object. \ + But current parser state is {0} +parser.expected.eof=Expected EOF token, but got {0} +parser.tokenizer.close.io=I/O error while closing JSON tokenizer +parser.invalid.token=Invalid token={0} at {1}. Expected tokens are: {2} +parser.state.err=Unknown value type {0} +parser.scope.err=Cannot be called for value {0} +parser.input.enc.detect.failed=Cannot auto-detect encoding, not enough chars +parser.input.enc.detect.ioerr=I/O error while auto-detecting the encoding of stream +parser.duplicate.key=Duplicate key ''{0}'' is not allowed + +generator.flush.io.err=I/O error while flushing generated JSON +generator.close.io.err=I/O error while closing JsonGenerator +generator.write.io.err=I/O error while writing in JsonGenerator +generator.illegal.method=Illegal method during JSON generation, \ + not valid in current context {0} +generator.double.infinite.nan=double value cannot be Infinite or NaN +generator.incomplete.json=Generating incomplete JSON +generator.illegal.multiple.text=Cannot generate more than one JSON text + +writer.write.already.called=write/writeObject/writeArray/close method is already called + +reader.read.already.called=read/readObject/readArray/close method is already called + +objbuilder.name.null=Name in JsonObject's name/value pair cannot be null +objbuilder.value.null=Value in JsonObject's name/value pair cannot be null +objbuilder.object.builder.null=Object builder that is used to create a value in JsonObject's name/value pair cannot be null +objbuilder.array.builder.null=Array builder that is used to create a value in JsonObject's name/value pair cannot be null + +arrbuilder.value.null=Cannot invoke add(null) while building JsonArray. +arrbuilder.object.builder.null=Object builder that is used to add a value to JSON array cannot be null +arrbuilder.array.builder.null=Array builder that is used to add a value to JSON array cannot be null +arrbuilder.valuelist.null=Index: {0}, Size: {1} + +tokenizer.unexpected.char=Unexpected char {0} at {1} +tokenizer.expected.char=Unexpected char {0} at {1}, expecting ''{2}'' +tokenizer.io.err=I/O error while parsing JSON + +pointer.format.invalid=A non-empty JSON Pointer must begin with a ''/'' +pointer.mapping.missing=The JSON Object ''{0}'' contains no mapping for the name ''{1}'' +pointer.reference.invalid=The reference value in a JSON Pointer must be a JSON Object or a JSON Array, was ''{0}'' +pointer.array.index.err=Array index format error, was ''{0}'' +pointer.array.index.illegal=Illegal integer format, was ''{0}'' + +noderef.value.add.err=The root value only allows adding a JSON object or array +noderef.value.cannot.remove=The JSON value at the root cannot be removed +noderef.object.missing=Non-existing name/value pair in the object for key {0} +noderef.array.index.err=An array item index is out of range. Index: {0}, Size: {1} + +patch.must.be.array=A JSON Patch must be an array of JSON Objects +patch.move.proper.prefix=The ''{0}'' path of the patch operation ''move'' is a proper prefix of the ''{1}'' path +patch.move.target.null=The ''{0}'' path of the patch operation ''move'' does not exist in target object +patch.test.failed=The JSON Patch operation ''test'' failed for path ''{0}'' and value ''{1}'' +patch.illegal.operation=Illegal value for the op member of the JSON Patch operation: ''{0}'' +patch.member.missing=The JSON Patch operation ''{0}'' must contain a ''{1}'' member +patch.operation.missing=The JSON Patch must contain ''op'' member
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonArrayTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonArrayTest.java new file mode 100644 index 0000000..fa2d9d1 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonArrayTest.java
@@ -0,0 +1,159 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.*; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Jitendra Kotamraju + */ +public class JsonArrayTest extends TestCase { + public JsonArrayTest(String testName) { + super(testName); + } + + public void testArrayEquals() throws Exception { + JsonArray expected = Json.createArrayBuilder() + .add(JsonValue.TRUE) + .add(JsonValue.FALSE) + .add(JsonValue.NULL) + .add(Integer.MAX_VALUE) + .add(Long.MAX_VALUE) + .add(Double.MAX_VALUE) + .add(Integer.MIN_VALUE) + .add(Long.MIN_VALUE) + .add(Double.MIN_VALUE) + .add(Json.createArrayBuilder().add("abc")) + .add(Json.createObjectBuilder().add("one", 1)) + .build(); + + StringWriter sw = new StringWriter(); + JsonWriter writer = Json.createWriter(sw); + writer.writeArray(expected); + writer.close(); + + JsonReader reader = Json.createReader(new StringReader(sw.toString())); + JsonArray actual = reader.readArray(); + reader.close(); + + assertEquals(expected, actual); + } + + public void testArrayEqualsUsingCollection() { + List<Object> list = new ArrayList<>(); + list.add(JsonValue.TRUE); + list.add(JsonValue.FALSE); + list.add(JsonValue.NULL); + list.add(Integer.MAX_VALUE); + list.add(Long.MAX_VALUE); + list.add(Double.MAX_VALUE); + list.add(Integer.MIN_VALUE); + list.add(Long.MIN_VALUE); + list.add(Double.MIN_VALUE); + list.add(Json.createArrayBuilder().add("abc")); + list.add(Json.createObjectBuilder().add("one", 1)); + + JsonArray expected = Json.createArrayBuilder(list).build(); + + StringWriter sw = new StringWriter(); + JsonWriter writer = Json.createWriter(sw); + writer.writeArray(expected); + writer.close(); + + JsonReader reader = Json.createReader(new StringReader(sw.toString())); + JsonArray actual = reader.readArray(); + reader.close(); + + assertEquals(expected, actual); + } + + public void testStringValue() throws Exception { + JsonArray array = Json.createArrayBuilder() + .add("John") + .build(); + assertEquals("John", array.getString(0)); + } + + public void testIntValue() throws Exception { + JsonArray array = Json.createArrayBuilder() + .add(20) + .build(); + assertEquals(20, array.getInt(0)); + } + + public void testAdd() { + JsonArray array = Json.createArrayBuilder().build(); + try { + array.add(JsonValue.FALSE); + fail("JsonArray#add() should throw UnsupportedOperationException"); + } catch(UnsupportedOperationException e) { + // Expected + } + } + + public void testRemove() { + JsonArray array = Json.createArrayBuilder().build(); + try { + array.remove(0); + fail("JsonArray#remove() should throw UnsupportedOperationException"); + } catch(UnsupportedOperationException e) { + // Expected + } + } + + public void testNumberView() throws Exception { + JsonArray array = Json.createArrayBuilder().add(20).add(10).build(); + + List<JsonNumber> numberList = array.getValuesAs(JsonNumber.class); + for(JsonNumber num : numberList) { + num.intValue(); + } + + assertEquals(20, array.getInt(0)); + assertEquals(10, array.getInt(1)); + } + + public void testArrayBuilderNpe() { + try { + JsonArray array = Json.createArrayBuilder().add((JsonValue)null).build(); + fail("JsonArrayBuilder#add(null) should throw NullPointerException"); + } catch(NullPointerException e) { + // Expected + } + } + + public void testHashCode() { + JsonArray array1 = Json.createArrayBuilder().add(1).add(2).add(3).build(); + assertTrue(array1.hashCode() == array1.hashCode()); //1st call compute hashCode, 2nd call returns cached value + + JsonArray array2 = Json.createArrayBuilder().add(1).add(2).add(3).build(); + assertTrue(array1.hashCode() == array2.hashCode()); + + JsonArray array3 = Json.createArrayBuilder().build(); //org.glassfish.json.JsonArrayBuilderImpl.JsonArrayImpl + JsonArray array4 = JsonValue.EMPTY_JSON_ARRAY; //jakarta.json.EmptyArray + + assertTrue(array3.equals(array4)); + assertTrue(array3.hashCode() == array4.hashCode()); //equal instances have same hashCode + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonBuilderFactoryTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonBuilderFactoryTest.java new file mode 100644 index 0000000..c41881b --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonBuilderFactoryTest.java
@@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import java.util.Map; +import jakarta.json.Json; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author lukas + */ +public class JsonBuilderFactoryTest { + + @Test + public void testArrayBuilder() { + JsonBuilderFactory builderFactory = Json.createBuilderFactory(null); + Assert.assertNotNull(builderFactory.createArrayBuilder()); + } + + @Test(expected = NullPointerException.class) + public void testArrayBuilderNPE() { + JsonBuilderFactory builderFactory = Json.createBuilderFactory(null); + builderFactory.createArrayBuilder(null); + } + + @Test + public void testArrayBuilderFromArray() { + JsonBuilderFactory builderFactory = Json.createBuilderFactory(null); + JsonArrayBuilder builder = builderFactory.createArrayBuilder(JsonBuilderTest.buildPhone()); + Assert.assertEquals(JsonBuilderTest.buildPhone(), builder.build()); + } + + @Test + public void testObjectBuilder() { + JsonBuilderFactory builderFactory = Json.createBuilderFactory(null); + Assert.assertNotNull(builderFactory.createObjectBuilder()); + } + + @Test(expected = NullPointerException.class) + public void testObjectBuilderNPE() { + JsonBuilderFactory builderFactory = Json.createBuilderFactory(null); + builderFactory.createObjectBuilder((JsonObject) null); + } + + @Test(expected = NullPointerException.class) + public void testObjectBuilderNPE_map() { + JsonBuilderFactory builderFactory = Json.createBuilderFactory(null); + builderFactory.createObjectBuilder((Map<String, Object>) null); + } + + @Test + public void testObjectBuilderFromObject() { + JsonBuilderFactory builderFactory = Json.createBuilderFactory(null); + JsonObjectBuilder builder = builderFactory.createObjectBuilder(JsonBuilderTest.buildPerson()); + Assert.assertEquals(JsonBuilderTest.buildPerson(), builder.build()); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonBuilderTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonBuilderTest.java new file mode 100644 index 0000000..20057e7 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonBuilderTest.java
@@ -0,0 +1,161 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * @author Jitendra Kotamraju + */ +public class JsonBuilderTest extends TestCase { + public JsonBuilderTest(String testName) { + super(testName); + } + + public void testEmptyObject() throws Exception { + JsonObject empty = Json.createObjectBuilder() + .build(); + + JsonObjectTest.testEmpty(empty); + } + + public void testEmptyArray() throws Exception { + JsonArray empty = Json.createArrayBuilder() + .build(); + + assertTrue(empty.isEmpty()); + } + + public void testObject() throws Exception { + JsonObject person = buildPerson(); + JsonObjectTest.testPerson(person); + } + + public void testNumber() throws Exception { + JsonObject person = buildPerson(); + JsonNumber number = person.getJsonNumber("age"); + assertEquals(25, number.intValueExact()); + assertEquals(25, number.intValue()); + assertTrue(number.isIntegral()); + JsonObjectTest.testPerson(person); + } + + public void testJsonObjectCopy() { + JsonObject person = buildPerson(); + final JsonObjectBuilder objectBuilder = Json.createObjectBuilder(person); + final JsonObject copyPerson = objectBuilder.build(); + + JsonNumber number = copyPerson.getJsonNumber("age"); + assertEquals(25, number.intValueExact()); + assertEquals(25, number.intValue()); + assertTrue(number.isIntegral()); + JsonObjectTest.testPerson(copyPerson); + + } + + public void testJsonObjectMap() { + Map<String, Object> person = buildPersonAsMap(); + final JsonObjectBuilder objectBuilder = Json.createObjectBuilder(person); + final JsonObject copyPerson = objectBuilder.build(); + + JsonNumber number = copyPerson.getJsonNumber("age"); + assertEquals(25, number.intValueExact()); + assertEquals(25, number.intValue()); + assertTrue(number.isIntegral()); + JsonObjectTest.testPerson(copyPerson); + } + + static Map<String, Object> buildPersonAsMap() { + Map<String, Object> person = new HashMap<>(); + person.put("firstName", "John"); + person.put("lastName", "Smith"); + person.put("age", 25); + + Map<String, Object> address = Optional.of(new HashMap<String, Object>()).get(); + address.put("streetAddress", "21 2nd Street"); + address.put("city", "New York"); + address.put("state", "NY"); + address.put("postalCode", "10021"); + + person.put("address", address); + person.put("mailingAddress", Optional.empty()); + + Collection<Map<String, Object>> phones = new ArrayList<>(); + + Map<String, Object> phone1 = new HashMap<>(); + phone1.put("type", "home"); + phone1.put("number", "212 555-1234"); + phones.add(phone1); + + Map<String, Object> phone2 = new HashMap<>(); + phone2.put("type", "fax"); + phone2.put("number", "646 555-4567"); + phones.add(phone2); + + person.put("phoneNumber", phones); + + return person; + } + + static JsonObject buildPerson() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + + static JsonObject buildAddress() { + return Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021") + .build(); + } + + static JsonArray buildPhone() { + return Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567")) + .build(); + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonCollectorTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonCollectorTest.java new file mode 100644 index 0000000..c71ac3d --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonCollectorTest.java
@@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import org.junit.BeforeClass; +import org.junit.Test; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonCollectors; +import org.glassfish.json.JsonUtil; + +import static org.junit.Assert.assertEquals; + +/** + * Some JSON query tests/examples, using Java stream operations, with JSON collectors. + * @author Kin-man Chung + */ +public class JsonCollectorTest { + + static JsonArray contacts; + + @BeforeClass + public static void setUpClass() { + // The JSON source + contacts = (JsonArray) JsonUtil.toJson( + "[ " + + " { 'name': 'Duke', " + + " 'age': 18, " + + " 'gender': 'M', " + + " 'phones': { " + + " 'home': '650-123-4567', " + + " 'mobile': '650-234-5678'}}," + + " { 'name': 'Jane', " + + " 'age': 23, " + + " 'gender': 'F', " + + " 'phones': { " + + " 'mobile': '707-999-5555'}}," + + " { 'name': 'Joanna', " + + " 'gender': 'F', " + + " 'phones': { " + + " 'mobile': '505-333-4444'}} " + + " ]"); + } + + @Test + public void testToJsonArray() { + /* + * Query: retrieve the names of female contacts + * Returns a JsonArray of names + */ + JsonArray result = contacts.getValuesAs(JsonObject.class).stream() + .filter(x->"F".equals(x.getString("gender"))) + .map(x-> x.get("name")) + .collect(JsonCollectors.toJsonArray()); + JsonValue expected = JsonUtil.toJson("['Jane','Joanna']"); + assertEquals(expected, result); + } + + @Test + public void testToJsonObject() { + /* + * Query: retrieve the names and mobile phones of female contacts + * Returns a JsonObject of name phones pairs + */ + JsonObject result = contacts.getValuesAs(JsonObject.class).stream() + .filter(x->"F".equals(x.getString("gender"))) + .collect(JsonCollectors.toJsonObject( + x->x.asJsonObject().getString("name"), + x->x.asJsonObject().getJsonObject("phones").get("mobile"))) + ; + JsonValue expected = JsonUtil.toJson( + "{'Jane': '707-999-5555', 'Joanna': '505-333-4444'}"); + assertEquals(expected, result); + } + + @Test + public void testGroupBy() { + /* + * Query: group the contacts according to gender + * Returns a JsonObject, with gender/constacts value pairs + */ + JsonObject result = contacts.getValuesAs(JsonObject.class).stream() + .collect(JsonCollectors.groupingBy(x->((JsonObject)x).getString("gender"))); + JsonValue expected = JsonUtil.toJson( + "{'F': " + + " [ " + + " { 'name': 'Jane', " + + " 'age': 23, " + + " 'gender': 'F', " + + " 'phones': { " + + " 'mobile': '707-999-5555'}}," + + " { 'name': 'Joanna', " + + " 'gender': 'F', " + + " 'phones': { " + + " 'mobile': '505-333-4444'}} " + + " ], " + + "'M': " + + " [ " + + " { 'name': 'Duke', " + + " 'age': 18, " + + " 'gender': 'M', " + + " 'phones': { " + + " 'home': '650-123-4567', " + + " 'mobile': '650-234-5678'}} " + + " ] " + + "}"); + + assertEquals(result,expected); + } + + static int index; //for keeping track of the array index + @Test + public void testQueryAndPatch() { + /* + * Query and patch: Increment the ages of contacts with an age entry + * PatchBuilder is used for building the necessary JsonPatch. + */ + index = -1; + JsonPatchBuilder builder = Json.createPatchBuilder(); + contacts.getValuesAs(JsonObject.class).stream() + .peek(p->index++) + .filter(p->p.containsKey("age")) + .forEach(p-> builder.replace("/"+index+"/age", p.getInt("age")+1)); + JsonArray result = builder.build().apply(contacts); + + JsonValue expected = (JsonArray) JsonUtil.toJson( + "[ " + + " { 'name': 'Duke', " + + " 'age': 19, " + + " 'gender': 'M', " + + " 'phones': { " + + " 'home': '650-123-4567', " + + " 'mobile': '650-234-5678'}}," + + " { 'name': 'Jane', " + + " 'age': 24, " + + " 'gender': 'F', " + + " 'phones': { " + + " 'mobile': '707-999-5555'}}," + + " { 'name': 'Joanna', " + + " 'gender': 'F', " + + " 'phones': { " + + " 'mobile': '505-333-4444'}} " + + " ]"); + + assertEquals(expected, result); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonDuplicateKeyTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonDuplicateKeyTest.java new file mode 100644 index 0000000..c95d04a --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonDuplicateKeyTest.java
@@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.StringReader; +import java.util.Collections; + +import org.glassfish.json.api.JsonConfig; +import org.junit.Test; + +import jakarta.json.Json; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonReader; +import jakarta.json.JsonReaderFactory; +import jakarta.json.stream.JsonParsingException; + +public class JsonDuplicateKeyTest { + @Test + public void testJsonReaderDuplicateKey1() { + String json = "{\"a\":\"b\",\"a\":\"c\"}"; + JsonReader jsonReader = Json.createReader(new StringReader(json)); + JsonObject jsonObject = jsonReader.readObject(); + assertEquals(jsonObject.getString("a"), "c"); + } + + @Test + public void testJsonReaderDuplicateKey2() { + String json = "{\"a\":\"b\",\"a\":\"c\"}"; + JsonReaderFactory jsonReaderFactory = Json.createReaderFactory(Collections.singletonMap(JsonConfig.REJECT_DUPLICATE_KEYS, true)); + JsonReader jsonReader = jsonReaderFactory.createReader(new StringReader(json)); + try { + jsonReader.readObject(); + fail(); + } catch (Exception e) { + assertTrue(e instanceof JsonParsingException); + assertEquals("Duplicate key 'a' is not allowed", e.getMessage()); + } + } + + @Test + public void testJsonObjectBuilderDuplcateKey1() { + JsonObjectBuilder objectBuilder = Json.createObjectBuilder(); + JsonObject jsonObject = objectBuilder.add("a", "b").add("a", "c").build(); + assertEquals(jsonObject.getString("a"), "c"); + } + + @Test + public void testJsonObjectBuilderDuplcateKey2() { + JsonBuilderFactory jsonBuilderFactory = Json.createBuilderFactory(Collections.singletonMap(JsonConfig.REJECT_DUPLICATE_KEYS, true)); + JsonObjectBuilder objectBuilder = jsonBuilderFactory.createObjectBuilder(); + try { + objectBuilder.add("a", "b").add("a", "c").build(); + fail(); + } catch (Exception e) { + assertTrue(e instanceof IllegalStateException); + assertEquals("Duplicate key 'a' is not allowed", e.getMessage()); + } + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonFieldTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonFieldTest.java new file mode 100644 index 0000000..4241573 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonFieldTest.java
@@ -0,0 +1,198 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.Json; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerationException; +import jakarta.json.stream.JsonGenerator; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.concurrent.Callable; + +/** + * Test for writing json field names without values. + * + * @author Roman Grigoriadi + */ +public class JsonFieldTest extends TestCase { + + public void testFieldAsOnlyMember() { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + + generator.writeStartObject(); + generator.writeKey("fName"); + generator.write("fValue"); + generator.writeEnd(); + + generator.close(); + assertEquals("{\"fName\":\"fValue\"}", sw.toString()); + } + + public void testFieldAsFirstMember() { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + + generator.writeStartObject(); + generator.writeKey("f1Name"); + generator.write("f1Value"); + generator.write("f2Name", "f2Value"); + generator.writeEnd(); + + generator.close(); + assertEquals("{\"f1Name\":\"f1Value\",\"f2Name\":\"f2Value\"}", sw.toString()); + } + + public void testFieldAsLastMember() { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + + generator.writeStartObject(); + generator.write("f1Name", "f1Value"); + generator.writeKey("f2Name"); + generator.write("f2Value"); + generator.writeEnd(); + + generator.close(); + assertEquals("{\"f1Name\":\"f1Value\",\"f2Name\":\"f2Value\"}", sw.toString()); + } + + + public void testFieldObject() { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + + generator.writeStartObject(); + generator.writeKey("f1Name"); + generator.writeStartObject(); + generator.write("innerFieldName", "innerFieldValue"); + generator.writeEnd(); + generator.write("f2Name", "f2Value"); + generator.writeEnd(); + + generator.close(); + assertEquals("{\"f1Name\":{\"innerFieldName\":\"innerFieldValue\"},\"f2Name\":\"f2Value\"}", sw.toString()); + } + + public void testFieldArray() { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + + generator.writeStartObject(); + generator.writeKey("f1Name"); + generator.writeStartArray(); + generator.write("arrayValue"); + generator.writeEnd(); + generator.write("f2Name", "f2Value"); + generator.writeEnd(); + + generator.close(); + assertEquals("{\"f1Name\":[\"arrayValue\"],\"f2Name\":\"f2Value\"}", sw.toString()); + } + + public void testFailFieldInField() { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + + generator.writeStartObject(); + generator.writeKey("f1Name"); + + try { + generator.write("f2Name", "f2Value"); + fail("Field value, start object/array expected"); + } catch (JsonGenerationException exception) { + //ok + } + } + + + public void testFailFieldKeyInArray() { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + + generator.writeStartArray(); + + try { + generator.writeKey("f1Value"); + fail("Not allowed in array ."); + } catch (JsonGenerationException exception) { + //ok + } + } + + public void testWriteString() { + assertEquals("{\"f1Name\":\"f1Value\"}", writeValue((gen)->gen.write("f1Value"))); + } + + public void testWriteBigDec() { + assertEquals("{\"f1Name\":10}", writeValue((gen)->gen.write(BigDecimal.TEN))); + } + + public void testWriteBigInt() { + assertEquals("{\"f1Name\":10}", writeValue((gen)->gen.write(BigInteger.TEN))); + } + + public void testWriteBool() { + assertEquals("{\"f1Name\":true}", writeValue((gen)->gen.write(true))); + } + + public void testWriteInt() { + assertEquals("{\"f1Name\":10}", writeValue((gen)->gen.write(10))); + } + + public void testWriteLong() { + assertEquals("{\"f1Name\":10}", writeValue((gen)->gen.write(10L))); + } + + public void testWriteDouble() { + assertEquals("{\"f1Name\":10.0}", writeValue((gen)->gen.write(10d))); + } + + public void testWriteNull() { + assertEquals("{\"f1Name\":null}", writeValue(JsonGenerator::writeNull)); + } + + public void testWriteJsonValue() { + JsonObjectBuilder builder = Json.createObjectBuilder(); + builder.add("first", "value"); + final JsonObject build = builder.build(); + assertEquals("{\"f1Name\":\"value\"}", writeValue((gen)->gen.write(build.getValue("/first")))); + } + + private String writeValue(WriteValueFunction writeValueCallback) { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + + generator.writeStartObject(); + generator.writeKey("f1Name"); + writeValueCallback.writeValue(generator); + generator.writeEnd(); + generator.close(); + return sw.toString(); + } + + private interface WriteValueFunction { + void writeValue(JsonGenerator generator); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonGeneratorFactoryTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonGeneratorFactoryTest.java new file mode 100644 index 0000000..183725c --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonGeneratorFactoryTest.java
@@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.*; +import jakarta.json.stream.JsonGenerator; +import jakarta.json.stream.JsonGeneratorFactory; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +/** + * Tests JsonGeneratorFactory + * + * @author Jitendra Kotamraju + */ +public class JsonGeneratorFactoryTest extends TestCase { + + public JsonGeneratorFactoryTest(String testName) { + super(testName); + } + + public void testGeneratorFactory() { + JsonGeneratorFactory generatorFactory = Json.createGeneratorFactory(null); + + JsonGenerator generator1 = generatorFactory.createGenerator(new StringWriter()); + generator1.writeStartArray().writeEnd(); + generator1.close(); + + JsonGenerator generator2 = generatorFactory.createGenerator(new StringWriter()); + generator2.writeStartArray().writeEnd(); + generator2.close(); + } + + public void testGeneratorFactoryWithConfig() { + Map<String, Object> config = new HashMap<>(); + config.put(JsonGenerator.PRETTY_PRINTING, true); + JsonGeneratorFactory generatorFactory = Json.createGeneratorFactory(config); + Map<String, ?> config1 = generatorFactory.getConfigInUse(); + if (config1.size() != 1) { + throw new JsonException("Expecting no of properties=1, got="+config1.size()); + } + assertTrue(config1.containsKey(JsonGenerator.PRETTY_PRINTING)); + + JsonGenerator generator1 = generatorFactory.createGenerator(new StringWriter()); + generator1.writeStartArray().writeEnd(); + generator1.close(); + + JsonGenerator generator2 = generatorFactory.createGenerator(new StringWriter()); + generator2.writeStartArray().writeEnd(); + generator2.close(); + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonGeneratorTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonGeneratorTest.java new file mode 100644 index 0000000..43745e0 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonGeneratorTest.java
@@ -0,0 +1,545 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; +import org.glassfish.json.api.BufferPool; + +import jakarta.json.*; +import jakarta.json.stream.*; +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +/** + * {@link JsonGenerator} tests + * + * @author Jitendra Kotamraju + */ +public class JsonGeneratorTest extends TestCase { + public JsonGeneratorTest(String testName) { + super(testName); + } + + public void testObjectWriter() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + testObject(generator); + generator.close(); + writer.close(); + + JsonReader reader = Json.createReader(new StringReader(writer.toString())); + JsonObject person = reader.readObject(); + JsonObjectTest.testPerson(person); + } + + public void testObjectStream() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + JsonGenerator generator = Json.createGenerator(out); + testObject(generator); + generator.close(); + out.close(); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + JsonReader reader = Json.createReader(in); + JsonObject person = reader.readObject(); + JsonObjectTest.testPerson(person); + reader.close(); + in.close(); + } + + static void testObject(JsonGenerator generator) throws Exception { + generator + .writeStartObject() + .write("firstName", "John") + .write("lastName", "Smith") + .write("age", 25) + .writeStartObject("address") + .write("streetAddress", "21 2nd Street") + .write("city", "New York") + .write("state", "NY") + .write("postalCode", "10021") + .writeEnd() + .writeStartArray("phoneNumber") + .writeStartObject() + .write("type", "home") + .write("number", "212 555-1234") + .writeEnd() + .writeStartObject() + .write("type", "fax") + .write("number", "646 555-4567") + .writeEnd() + .writeEnd() + .writeEnd(); + } + + public void testArray() throws Exception { + Writer sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + generator + .writeStartArray() + .writeStartObject() + .write("type", "home") + .write("number", "212 555-1234") + .writeEnd() + .writeStartObject() + .write("type", "fax") + .write("number", "646 555-4567") + .writeEnd() + .writeEnd(); + generator.close(); + } + + // tests JsonGenerator when JsonValue is used for generation + public void testJsonValue() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator + .writeStartObject() + .write("firstName", "John") + .write("lastName", "Smith") + .write("age", 25) + .write("address", JsonBuilderTest.buildAddress()) + .write("phoneNumber", JsonBuilderTest.buildPhone()) + .writeEnd(); + generator.close(); + writer.close(); + + JsonReader reader = Json.createReader(new StringReader(writer.toString())); + JsonObject person = reader.readObject(); + JsonObjectTest.testPerson(person); + } + + public void testArrayString() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartArray().write("string").writeEnd(); + generator.close(); + writer.close(); + + assertEquals("[\"string\"]", writer.toString()); + } + + public void testEscapedString() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartArray().write("\u0000").writeEnd(); + generator.close(); + writer.close(); + + assertEquals("[\"\\u0000\"]", writer.toString()); + } + + public void testEscapedString1() throws Exception { + String expected = "\u0000\u00ff"; + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + generator.writeStartArray().write("\u0000\u00ff").writeEnd(); + generator.close(); + sw.close(); + + JsonReader jr = Json.createReader(new StringReader(sw.toString())); + JsonArray array = jr.readArray(); + String got = array.getString(0); + jr.close(); + + assertEquals(expected, got); + } + + public void testGeneratorEquals() throws Exception { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + generator.writeStartArray() + .write(JsonValue.TRUE) + .write(JsonValue.FALSE) + .write(JsonValue.NULL) + .write(Integer.MAX_VALUE) + .write(Long.MAX_VALUE) + .write(Double.MAX_VALUE) + .write(Integer.MIN_VALUE) + .write(Long.MIN_VALUE) + .write(Double.MIN_VALUE) + .writeEnd(); + generator.close(); + + JsonReader reader = Json.createReader(new StringReader(sw.toString())); + JsonArray expected = reader.readArray(); + reader.close(); + + JsonArray actual = Json.createArrayBuilder() + .add(JsonValue.TRUE) + .add(JsonValue.FALSE) + .add(JsonValue.NULL) + .add(Integer.MAX_VALUE) + .add(Long.MAX_VALUE) + .add(Double.MAX_VALUE) + .add(Integer.MIN_VALUE) + .add(Long.MIN_VALUE) + .add(Double.MIN_VALUE) + .build(); + + assertEquals(expected, actual); + } + + public void testPrettyObjectWriter() throws Exception { + StringWriter writer = new StringWriter(); + Map<String, Object> config = new HashMap<>(); + config.put(JsonGenerator.PRETTY_PRINTING, true); + JsonGenerator generator = Json.createGeneratorFactory(config) + .createGenerator(writer); + testObject(generator); + generator.close(); + writer.close(); + + JsonReader reader = Json.createReader(new StringReader(writer.toString())); + JsonObject person = reader.readObject(); + JsonObjectTest.testPerson(person); + } + + public void testPrettyPrinting() throws Exception { + String[][] lines = {{"firstName", "John"}, {"lastName", "Smith"}}; + StringWriter writer = new StringWriter(); + Map<String, Object> config = new HashMap<>(); + config.put(JsonGenerator.PRETTY_PRINTING, true); + JsonGenerator generator = Json.createGeneratorFactory(config) + .createGenerator(writer); + generator.writeStartObject() + .write("firstName", "John") + .write("lastName", "Smith") + .writeEnd(); + generator.close(); + writer.close(); + + BufferedReader reader = new BufferedReader(new StringReader(writer.toString())); + int numberOfLines = 0; + String line; + while ((line = reader.readLine()) != null) { + numberOfLines++; + if (numberOfLines > 1 && numberOfLines < 4) { + assertTrue(line.contains("\"" + lines[numberOfLines - 2][0] + "\": \"" + lines[numberOfLines - 2][1] + "\"")); + } + } + assertEquals(4, numberOfLines); + } + + public void testPrettyObjectStream() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Map<String, Object> config = new HashMap<>(); + config.put(JsonGenerator.PRETTY_PRINTING, true); + JsonGenerator generator = Json.createGeneratorFactory(config) + .createGenerator(out); + testObject(generator); + generator.close(); + out.close(); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + JsonReader reader = Json.createReader(in); + JsonObject person = reader.readObject(); + JsonObjectTest.testPerson(person); + reader.close(); + in.close(); + } + + public void testGenerationException1() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartObject(); + try { + generator.writeStartObject(); + fail("Expected JsonGenerationException, writeStartObject() cannot be called more than once"); + } catch (JsonGenerationException je) { + // Expected exception + } + } + + public void testGenerationException2() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartObject(); + try { + generator.writeStartArray(); + fail("Expected JsonGenerationException, writeStartArray() is valid in no context"); + } catch (JsonGenerationException je) { + // Expected exception + } + } + + public void testGenerationException3() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + try { + generator.close(); + fail("Expected JsonGenerationException, no JSON is generated"); + } catch (JsonGenerationException je) { + // Expected exception + } + } + + public void testGenerationException4() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartArray(); + try { + generator.close(); + fail("Expected JsonGenerationException, writeEnd() is not called"); + } catch (JsonGenerationException je) { + // Expected exception + } + } + + public void testGenerationException5() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartObject(); + try { + generator.close(); + fail("Expected JsonGenerationException, writeEnd() is not called"); + } catch (JsonGenerationException je) { + // Expected exception + } + } + + public void testGenerationException6() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartObject().writeEnd(); + try { + generator.writeStartObject(); + fail("Expected JsonGenerationException, cannot generate one more JSON text"); + } catch (JsonGenerationException je) { + // Expected exception + } + } + + public void testGenerationException7() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartArray().writeEnd(); + try { + generator.writeStartArray(); + fail("Expected JsonGenerationException, cannot generate one more JSON text"); + } catch (JsonGenerationException je) { + // Expected exception + } + } + + + public void testGenerationException8() throws Exception { + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject(); + try { + generator.write(JsonValue.TRUE); + fail("Expected JsonGenerationException, cannot generate one more JSON text"); + } catch (JsonGenerationException je) { + // Expected exception + } + } + + public void testGenerationException9() throws Exception { + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject(); + try { + generator.write("name"); + fail("Expected JsonGenerationException, cannot generate one more JSON text"); + } catch (JsonGenerationException je) { + // Expected exception + } + } + + public void testGeneratorArrayDouble() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartArray(); + try { + generator.write(Double.NaN); + fail("JsonGenerator.write(Double.NaN) should produce NumberFormatException"); + } catch (NumberFormatException ne) { + // expected + } + try { + generator.write(Double.POSITIVE_INFINITY); + fail("JsonGenerator.write(Double.POSITIVE_INIFINITY) should produce NumberFormatException"); + } catch (NumberFormatException ne) { + // expected + } + try { + generator.write(Double.NEGATIVE_INFINITY); + fail("JsonGenerator.write(Double.NEGATIVE_INIFINITY) should produce NumberFormatException"); + } catch (NumberFormatException ne) { + // expected + } + generator.writeEnd(); + generator.close(); + } + + public void testGeneratorObjectDouble() throws Exception { + StringWriter writer = new StringWriter(); + JsonGenerator generator = Json.createGenerator(writer); + generator.writeStartObject(); + try { + generator.write("foo", Double.NaN); + fail("JsonGenerator.write(String, Double.NaN) should produce NumberFormatException"); + } catch (NumberFormatException ne) { + // expected + } + try { + generator.write("foo", Double.POSITIVE_INFINITY); + fail("JsonGenerator.write(String, Double.POSITIVE_INIFINITY) should produce NumberFormatException"); + } catch (NumberFormatException ne) { + // expected + } + try { + generator.write("foo", Double.NEGATIVE_INFINITY); + fail("JsonGenerator.write(String, Double.NEGATIVE_INIFINITY) should produce NumberFormatException"); + } catch (NumberFormatException ne) { + // expected + } + generator.writeEnd(); + generator.close(); + } + + public void testIntGenerator() throws Exception { + Random r = new Random(System.currentTimeMillis()); + JsonGeneratorFactory gf = Json.createGeneratorFactory(null); + JsonReaderFactory rf = Json.createReaderFactory(null); + JsonBuilderFactory bf = Json.createBuilderFactory(null); + for(int i=0; i < 100000; i++) { + int num = r.nextInt(); + StringWriter sw = new StringWriter(); + JsonGenerator generator = gf.createGenerator(sw); + generator.writeStartArray().write(num).writeEnd().close(); + + JsonReader reader = rf.createReader(new StringReader(sw.toString())); + JsonArray got = reader.readArray(); + reader.close(); + + JsonArray expected = bf.createArrayBuilder().add(num).build(); + + assertEquals(expected, got); + } + } + + public void testGeneratorBuf() throws Exception { + JsonGeneratorFactory gf = Json.createGeneratorFactory(null); + JsonReaderFactory rf = Json.createReaderFactory(null); + JsonBuilderFactory bf = Json.createBuilderFactory(null); + StringBuilder sb = new StringBuilder(); + int value = 10; + for(int i=0; i < 25000; i++) { + sb.append('a'); + String name = sb.toString(); + StringWriter sw = new StringWriter(); + JsonGenerator generator = gf.createGenerator(sw); + generator.writeStartObject().write(name, value).writeEnd().close(); + + JsonReader reader = rf.createReader(new StringReader(sw.toString())); + JsonObject got = reader.readObject(); + reader.close(); + + JsonObject expected = bf.createObjectBuilder().add(name, value).build(); + + assertEquals(expected, got); + } + } + + public void testBufferPoolFeature() { + final JsonParserTest.MyBufferPool bufferPool = new JsonParserTest.MyBufferPool(1024); + Map<String, Object> config = new HashMap<String, Object>() {{ + put(BufferPool.class.getName(), bufferPool); + }}; + + JsonGeneratorFactory factory = Json.createGeneratorFactory(config); + JsonGenerator generator = factory.createGenerator(new StringWriter()); + generator.writeStartArray(); + generator.writeEnd(); + generator.close(); + assertTrue(bufferPool.isTakeCalled()); + assertTrue(bufferPool.isRecycleCalled()); + } + + public void testBufferSizes() { + JsonReaderFactory rf = Json.createReaderFactory(null); + JsonBuilderFactory bf = Json.createBuilderFactory(null); + for(int size=10; size < 1000; size++) { + final JsonParserTest.MyBufferPool bufferPool = new JsonParserTest.MyBufferPool(size); + Map<String, Object> config = new HashMap<String, Object>() {{ + put(BufferPool.class.getName(), bufferPool); + }}; + JsonGeneratorFactory gf = Json.createGeneratorFactory(config); + + StringBuilder sb = new StringBuilder(); + int value = 10; + for(int i=0; i < 1500; i++) { + sb.append('a'); + String name = sb.toString(); + StringWriter sw = new StringWriter(); + JsonGenerator generator = gf.createGenerator(sw); + generator.writeStartObject().write(name, value).writeEnd().close(); + + JsonReader reader = rf.createReader(new StringReader(sw.toString())); + JsonObject got = reader.readObject(); + reader.close(); + + JsonObject expected = bf.createObjectBuilder().add(name, value).build(); + + assertEquals(expected, got); + } + + } + } + + public void testString() throws Exception { + escapedString(""); + escapedString("abc"); + escapedString("abc\f"); + escapedString("abc\na"); + escapedString("abc\tabc"); + escapedString("abc\n\tabc"); + escapedString("abc\n\tabc\r"); + escapedString("\n\tabc\r"); + escapedString("\bab\tb\rc\\\"\ftesting1234"); + escapedString("\f\babcdef\tb\rc\\\"\ftesting1234"); + } + + void escapedString(String expected) throws Exception { + StringWriter sw = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sw); + generator.writeStartArray().write(expected).writeEnd(); + generator.close(); + sw.close(); + + JsonReader jr = Json.createReader(new StringReader(sw.toString())); + JsonArray array = jr.readArray(); + String got = array.getString(0); + jr.close(); + + assertEquals(expected, got); + } + + public void testFlush() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator gen = Json.createGenerator(baos); + gen.writeStartObject().writeEnd(); + gen.flush(); + + assertEquals("{}", baos.toString("UTF-8")); + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonMergePatchDiffTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonMergePatchDiffTest.java new file mode 100644 index 0000000..24f8f8b --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonMergePatchDiffTest.java
@@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * + * @author Alex Soto + * + */ +@RunWith(Parameterized.class) +public class JsonMergePatchDiffTest { + + @Parameters(name = "{index}: ({0})={1}") + public static Iterable<Object[]> data() throws Exception { + List<Object[]> examples = new ArrayList<Object[]>(); + JsonArray data = loadData(); + for (JsonValue jsonValue : data) { + JsonObject test = (JsonObject) jsonValue; + Object[] testData = new Object[4]; + testData[0] = test.get("original"); + testData[1] = test.get("target"); + testData[2] = test.get("expected"); + testData[3] = createExceptionClass((JsonString)test.get("exception")); + + examples.add(testData); + } + + return examples; + } + + private static Class<? extends Exception> createExceptionClass( + JsonString exceptionClassName) throws ClassNotFoundException { + if (exceptionClassName != null) { + return (Class<? extends Exception>) Class + .forName(exceptionClassName.getString()); + } + return null; + } + + private static JsonArray loadData() { + InputStream testData = JsonPatchTest.class + .getResourceAsStream("/jsonmergepatchdiff.json"); + JsonReader reader = Json.createReader(testData); + JsonArray data = (JsonArray) reader.read(); + return data; + } + + private JsonValue original; + private JsonValue target; + private JsonValue expected; + private Class<? extends Exception> expectedException; + + public JsonMergePatchDiffTest(JsonValue original, JsonValue target, + JsonValue expected, Class<? extends Exception> expectedException) { + super(); + this.original = original; + this.target = target; + this.expected = expected; + this.expectedException = expectedException; + } + @Test + public void shouldExecuteJsonMergePatchDiffOperationsToJsonDocument() { + try { + JsonValue output = Json.createMergeDiff(original, target).toJsonValue(); + assertThat(output, is(expected)); + assertThat(expectedException, nullValue()); + } catch (Exception e) { + if (expectedException == null) { + fail(e.getMessage()); + } else { + assertThat(e, instanceOf(expectedException)); + } + } + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonMergePatchTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonMergePatchTest.java new file mode 100644 index 0000000..d839140 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonMergePatchTest.java
@@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * + * @author Alex Soto + * + */ +@RunWith(Parameterized.class) +public class JsonMergePatchTest { + + @Parameters(name = "{index}: ({0})={1}") + public static Iterable<Object[]> data() throws Exception { + List<Object[]> examples = new ArrayList<Object[]>(); + JsonArray data = loadData(); + for (JsonValue jsonValue : data) { + JsonObject test = (JsonObject) jsonValue; + Object[] testData = new Object[4]; + testData[0] = test.get("patch"); + testData[1] = test.get("target"); + testData[2] = test.get("expected"); + testData[3] = createExceptionClass((JsonString)test.get("exception")); + + examples.add(testData); + } + + return examples; + } + + private static Class<? extends Exception> createExceptionClass( + JsonString exceptionClassName) throws ClassNotFoundException { + if (exceptionClassName != null) { + return (Class<? extends Exception>) Class + .forName(exceptionClassName.getString()); + } + return null; + } + + private static JsonArray loadData() { + InputStream testData = JsonPatchTest.class + .getResourceAsStream("/jsonmergepatch.json"); + JsonReader reader = Json.createReader(testData); + JsonArray data = (JsonArray) reader.read(); + return data; + } + + private JsonValue patch; + private JsonValue target; + private JsonValue expected; + private Class<? extends Exception> expectedException; + + public JsonMergePatchTest(JsonValue patch, JsonValue target, + JsonValue expected, Class<? extends Exception> expectedException) { + super(); + this.patch = patch; + this.target = target; + this.expected = expected; + this.expectedException = expectedException; + } + + @Test + public void shouldExecuteJsonMergePatchDiffOperationsToJsonDocument() { + try { + JsonValue output = Json.createMergePatch(patch).apply(target); + assertThat(output, is(expected)); + assertThat(expectedException, nullValue()); + } catch (Exception e) { + if (expectedException == null) { + fail(e.getMessage()); + } else { + assertThat(e, instanceOf(expectedException)); + } + } + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonNumberTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonNumberTest.java new file mode 100644 index 0000000..e830dbb --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonNumberTest.java
@@ -0,0 +1,219 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.*; +import java.io.StringReader; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * @author Jitendra Kotamraju + */ +public class JsonNumberTest extends TestCase { + public JsonNumberTest(String testName) { + super(testName); + } + + public void testFloating() throws Exception { + JsonArray array1 = Json.createArrayBuilder().add(10.4).build(); + JsonReader reader = Json.createReader(new StringReader("[10.4]")); + JsonArray array2 = reader.readArray(); + + assertEquals(array1.get(0), array2.get(0)); + assertEquals(array1, array2); + } + + public void testBigDecimal() throws Exception { + JsonArray array1 = Json.createArrayBuilder().add(new BigDecimal("10.4")).build(); + JsonReader reader = Json.createReader(new StringReader("[10.4]")); + JsonArray array2 = reader.readArray(); + + assertEquals(array1.get(0), array2.get(0)); + assertEquals(array1, array2); + } + + public void testIntNumberType() throws Exception { + JsonArray array1 = Json.createArrayBuilder() + .add(Integer.MIN_VALUE) + .add(Integer.MAX_VALUE) + .add(Integer.MIN_VALUE + 1) + .add(Integer.MAX_VALUE - 1) + .add(12) + .add(12l) + .add(new BigInteger("0")) + .build(); + testNumberType(array1, true); + + StringReader sr = new StringReader("[" + + "-2147483648, " + + "2147483647, " + + "-2147483647, " + + "2147483646, " + + "12, " + + "12, " + + "0 " + + "]"); + JsonReader reader = Json.createReader(sr); + JsonArray array2 = reader.readArray(); + reader.close(); + testNumberType(array2, true); + + assertEquals(array1, array2); + } + + private void testNumberType(JsonArray array, boolean integral) { + for (JsonValue value : array) { + assertEquals(integral, ((JsonNumber) value).isIntegral()); + } + } + + public void testLongNumberType() throws Exception { + JsonArray array1 = Json.createArrayBuilder() + .add(Long.MIN_VALUE) + .add(Long.MAX_VALUE) + .add(Long.MIN_VALUE + 1) + .add(Long.MAX_VALUE - 1) + .add((long) Integer.MIN_VALUE - 1) + .add((long) Integer.MAX_VALUE + 1) + .build(); + testNumberType(array1, true); + + StringReader sr = new StringReader("[" + + "-9223372036854775808, " + + "9223372036854775807, " + + "-9223372036854775807, " + + "9223372036854775806, " + + "-2147483649, " + + "2147483648 " + + "]"); + JsonReader reader = Json.createReader(sr); + JsonArray array2 = reader.readArray(); + reader.close(); + testNumberType(array2, true); + + assertEquals(array1, array2); + } + + +// public void testBigIntegerNumberType() throws Exception { +// JsonArray array1 = new JsonBuilder() +// .startArray() +// .add(new BigInteger("-9223372036854775809")) +// .add(new BigInteger("9223372036854775808")) +// .add(new BigInteger("012345678901234567890")) +// .end() +// .build(); +// testNumberType(array1, JsonNumber.NumberType.BIG_INTEGER); +// +// StringReader sr = new StringReader("[" + +// "-9223372036854775809, " + +// "9223372036854775808, " + +// "12345678901234567890 " + +// "]"); +// JsonReader reader = new JsonReader(sr); +// JsonArray array2 = reader.readArray(); +// reader.close(); +// testNumberType(array2, JsonNumber.NumberType.BIG_INTEGER); +// +// assertEquals(array1, array2); +// } + + public void testBigDecimalNumberType() throws Exception { + JsonArray array1 = Json.createArrayBuilder() + .add(12d) + .add(12.0d) + .add(12.1d) + .add(Double.MIN_VALUE) + .add(Double.MAX_VALUE) + .build(); + testNumberType(array1, false); + + StringReader sr = new StringReader("[" + + "12.0, " + + "12.0, " + + "12.1, " + + "4.9E-324, " + + "1.7976931348623157E+308 " + + "]"); + JsonReader reader = Json.createReader(sr); + JsonArray array2 = reader.readArray(); + reader.close(); + testNumberType(array2, false); + + assertEquals(array1, array2); + } + + public void testMinMax() throws Exception { + JsonArray expected = Json.createArrayBuilder() + .add(Integer.MIN_VALUE) + .add(Integer.MAX_VALUE) + .add(Long.MIN_VALUE) + .add(Long.MAX_VALUE) + .add(Double.MIN_VALUE) + .add(Double.MAX_VALUE) + .build(); + + StringWriter sw = new StringWriter(); + JsonWriter writer = Json.createWriter(sw); + writer.writeArray(expected); + writer.close(); + + JsonReader reader = Json.createReader(new StringReader(sw.toString())); + JsonArray actual = reader.readArray(); + reader.close(); + + assertEquals(expected, actual); + } + + public void testLeadingZeroes() { + JsonArray array = Json.createArrayBuilder() + .add(0012.1d) + .build(); + + StringWriter sw = new StringWriter(); + JsonWriter jw = Json.createWriter(sw); + jw.write(array); + jw.close(); + + assertEquals("[12.1]", sw.toString()); + } + + public void testBigIntegerExact() { + try { + JsonArray array = Json.createArrayBuilder().add(12345.12345).build(); + array.getJsonNumber(0).bigIntegerValueExact(); + fail("Expected Arithmetic exception"); + } catch (ArithmeticException expected) { + // no-op + } + } + + public void testHashCode() { + JsonNumber jsonNumber1 = Json.createValue(1); + assertTrue(jsonNumber1.hashCode() == jsonNumber1.bigDecimalValue().hashCode()); + + JsonNumber jsonNumber2 = Json.createValue(1); + + assertTrue(jsonNumber1.equals(jsonNumber2)); + assertTrue(jsonNumber1.hashCode() == jsonNumber2.hashCode()); + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonObjectTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonObjectTest.java new file mode 100644 index 0000000..a0ac06c --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonObjectTest.java
@@ -0,0 +1,232 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import java.io.StringReader; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +import jakarta.json.*; + +/** + * @author Jitendra Kotamraju + */ +public class JsonObjectTest extends TestCase { + public JsonObjectTest(String testName) { + super(testName); + } + + public void test() { + } + + public void testEmptyObjectEquals() throws Exception { + JsonObject empty1 = Json.createObjectBuilder() + .build(); + + JsonObject empty2 = Json.createObjectBuilder() + .build(); + + assertEquals(empty1, empty2); + } + + public void testPersonObjectEquals() throws Exception { + JsonObject person1 = JsonBuilderTest.buildPerson(); + JsonObject person2 = JsonReaderTest.readPerson(); + + assertEquals(person1, person2); + } + + public void testGetStringOrDefault() throws Exception { + JsonObject object = Json.createObjectBuilder() + .add("string", "value") + .add("number", 25) + .add("boolean", false) + .build(); + assertEquals("value", object.getString("string", "default")); + assertEquals("default", object.getString("missing", "default")); + assertEquals("default", object.getString("number", "default")); + } + + public void testGetIntOrDefault() throws Exception { + JsonObject object = Json.createObjectBuilder() + .add("string", "value") + .add("number", 25) + .add("boolean", false) + .build(); + assertEquals(25, object.getInt("number", 10)); + assertEquals(10, object.getInt("missing", 10)); + assertEquals(10, object.getInt("string", 10)); + } + + public void testGetBooleanOrDefault() throws Exception { + JsonObject object = Json.createObjectBuilder() + .add("string", "value") + .add("number", 25) + .add("boolean", false) + .build(); + assertFalse(object.getBoolean("boolean", true)); + assertTrue(object.getBoolean("missing", true)); + assertTrue(object.getBoolean("string", true)); + } + + static void testPerson(JsonObject person) { + assertEquals(5, person.size()); + assertEquals("John", person.getString("firstName")); + assertEquals("Smith", person.getString("lastName")); + assertEquals(25, person.getJsonNumber("age").intValue()); + assertEquals(25, person.getInt("age")); + + JsonObject address = person.getJsonObject("address"); + assertEquals(4, address.size()); + assertEquals("21 2nd Street", address.getString("streetAddress")); + assertEquals("New York", address.getString("city")); + assertEquals("NY", address.getString("state")); + assertEquals("10021", address.getString("postalCode")); + + JsonArray phoneNumber = person.getJsonArray("phoneNumber"); + assertEquals(2, phoneNumber.size()); + JsonObject home = phoneNumber.getJsonObject(0); + assertEquals(2, home.size()); + assertEquals("home", home.getString("type")); + assertEquals("212 555-1234", home.getString("number")); + assertEquals("212 555-1234", home.getString("number")); + + JsonObject fax = phoneNumber.getJsonObject(1); + assertEquals(2, fax.size()); + assertEquals("fax", fax.getString("type")); + assertEquals("646 555-4567", fax.getString("number")); + + assertEquals("\"646 555-4567\"", fax.getJsonString("number").toString()); + } + + static void testEmpty(JsonObject empty) { + assertTrue(empty.isEmpty()); + } + + public void testClassCastException() { + JsonObject obj = Json.createObjectBuilder() + .add("foo", JsonValue.FALSE).build(); + try { + obj.getJsonNumber("foo"); + fail("Expected ClassCastException for casting JsonValue.FALSE to JsonNumber"); + } catch (ClassCastException ce) { + // Expected + } + } + + public void testPut() { + JsonObject obj = Json.createObjectBuilder().add("foo", 1).build(); + try { + obj.put("bar", JsonValue.FALSE); + fail("JsonObject#put() should throw UnsupportedOperationException"); + } catch(UnsupportedOperationException e) { + // Expected + } + } + + public void testRemove() { + JsonObject obj = Json.createObjectBuilder().add("foo", 1).build(); + try { + obj.remove("foo"); + fail("JsonObject#remove() should throw UnsupportedOperationException"); + } catch(UnsupportedOperationException e) { + // Expected + } + } + + public void testObjectBuilderWithVariousValues() { + JsonObject expected = Json.createObjectBuilder() + .add("a", JsonValue.TRUE) + .add("b", JsonValue.FALSE) + .add("c", JsonValue.NULL) + .add("d", Integer.MAX_VALUE) + .add("e", Long.MAX_VALUE) + .add("f", Double.MAX_VALUE) + .add("g", Integer.MIN_VALUE) + .add("h", Long.MIN_VALUE) + .add("i", Double.MIN_VALUE) + .add("j", Json.createArrayBuilder().add("abc")) + .add("k", Json.createObjectBuilder().add("one", 1)) + .build(); + + StringWriter sw = new StringWriter(); + JsonWriter writer = Json.createWriter(sw); + writer.writeObject(expected); + writer.close(); + + JsonReader reader = Json.createReader(new StringReader(sw.toString())); + JsonObject actual = reader.readObject(); + reader.close(); + + assertEquals(expected, actual); + } + + public void testObjectBuilderWithMap() { + Map<String, Object> map = new HashMap<>(); + map.put("a", JsonValue.TRUE); + map.put("b", JsonValue.FALSE); + map.put("c", JsonValue.NULL); + map.put("d", Integer.MAX_VALUE); + map.put("e", Long.MAX_VALUE); + map.put("f", Double.MAX_VALUE); + map.put("g", Integer.MIN_VALUE); + map.put("h", Long.MIN_VALUE); + map.put("i", Double.MIN_VALUE); + map.put("j", Json.createArrayBuilder().add("abc")); + map.put("k", Json.createObjectBuilder().add("one", 1)); + + JsonObject expected = Json.createObjectBuilder(map).build(); + + StringWriter sw = new StringWriter(); + JsonWriter writer = Json.createWriter(sw); + writer.writeObject(expected); + writer.close(); + + JsonReader reader = Json.createReader(new StringReader(sw.toString())); + JsonObject actual = reader.readObject(); + reader.close(); + + assertEquals(expected, actual); + } + + public void testObjectBuilderNpe() { + try { + JsonObject obj = Json.createObjectBuilder().add(null, 1).build(); + fail("JsonObjectBuilder#add(null, 1) should throw NullPointerException"); + } catch(NullPointerException e) { + // Expected + } + } + + public void testHashCode() { + JsonObject object1 = Json.createObjectBuilder().add("a", 1).add("b", 2).add("c", 3).build(); + assertTrue(object1.hashCode() == object1.hashCode()); //1st call compute hashCode, 2nd call returns cached value + + JsonObject object2 = Json.createObjectBuilder().add("a", 1).add("b", 2).add("c", 3).build(); + assertTrue(object1.hashCode() == object2.hashCode()); + + JsonObject object3 = Json.createObjectBuilder().build(); //org.glassfish.json.JsonArrayBuilderImpl.JsonArrayImpl + JsonObject object4 = JsonValue.EMPTY_JSON_OBJECT; //jakarta.json.EmptyObject + + assertTrue(object3.equals(object4)); + assertTrue(object3.hashCode() == object4.hashCode()); //equal instances have same hashCode + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonParserFactoryTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonParserFactoryTest.java new file mode 100644 index 0000000..c222cdb --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonParserFactoryTest.java
@@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.Json; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParserFactory; +import java.io.StringReader; +import java.util.HashMap; +import java.util.Map; + +/** + * Tests JsonParserFactory + * + * @author Jitendra Kotamraju + */ +public class JsonParserFactoryTest extends TestCase { + + public JsonParserFactoryTest(String testName) { + super(testName); + } + + public void testParserFactory() { + JsonParserFactory parserFactory = Json.createParserFactory(null); + JsonParser parser1 = parserFactory.createParser(new StringReader("[]")); + parser1.close(); + JsonParser parser2 = parserFactory.createParser(new StringReader("[]")); + parser2.close(); + } + + public void testParserFactoryWithConfig() { + Map<String, ?> config = new HashMap<>(); + JsonParserFactory parserFactory = Json.createParserFactory(config); + JsonParser parser1 = parserFactory.createParser(new StringReader("[]")); + parser1.close(); + JsonParser parser2 = parserFactory.createParser(new StringReader("[]")); + parser2.close(); + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonParserSkipTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonParserSkipTest.java new file mode 100644 index 0000000..72a17fd --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonParserSkipTest.java
@@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import java.io.StringReader; +import jakarta.json.Json; +import jakarta.json.stream.JsonParser; +import junit.framework.TestCase; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +/** + * + * @author lukas + */ +public class JsonParserSkipTest extends TestCase { + + public void testSkipArrayReader() { + try (JsonParser parser = Json.createParser(new StringReader("[[],[[]]]"))) { + testSkipArray(parser); + } + } + + public void testSkipArrayStructure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createArrayBuilder() + .add(Json.createArrayBuilder()) + .add(Json.createArrayBuilder() + .add(Json.createArrayBuilder())) + .build())) { + testSkipArray(parser); + } + } + + private static void testSkipArray(JsonParser parser) { + assertEquals(JsonParser.Event.START_ARRAY, parser.next()); + parser.skipArray(); + assertEquals(false, parser.hasNext()); + } + + public void testSkipArrayInObjectReader() { + try (JsonParser parser = Json.createParser(new StringReader("{\"array\":[[],[[]]],\"object\":\"value2\"}"))) { + testSkipArrayInObject(parser); + } + } + + public void testSkipArrayInObjectStructure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createObjectBuilder().add("array", Json.createArrayBuilder() + .add(Json.createArrayBuilder()) + .add(Json.createArrayBuilder() + .add(Json.createArrayBuilder())) + ).add("object", "value2") + .build())) { + testSkipArrayInObject(parser); + } + } + + private static void testSkipArrayInObject(JsonParser parser) { + assertEquals(JsonParser.Event.START_OBJECT, parser.next()); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + assertEquals(JsonParser.Event.START_ARRAY, parser.next()); + parser.skipArray(); + assertTrue(parser.hasNext()); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + assertEquals(JsonParser.Event.VALUE_STRING, parser.next()); + assertEquals(JsonParser.Event.END_OBJECT, parser.next()); + assertFalse(parser.hasNext()); + } + + public void testSkipObjectReader() { + try (JsonParser parser = Json.createParser(new StringReader("{\"array\":[],\"objectToSkip\":{\"huge key\":\"huge value\"},\"simple\":2}"))) { + testSkipObject(parser); + } + } + + public void testSkipObjectStructure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createObjectBuilder() + .add("array", Json.createArrayBuilder().build()) + .add("objectToSkip", Json.createObjectBuilder().add("huge key", "huge value")) + .add("simple", 2) + .build())) { + testSkipObject(parser); + } + } + + private static void testSkipObject(JsonParser parser) { + assertEquals(JsonParser.Event.START_OBJECT, parser.next()); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + assertEquals(JsonParser.Event.START_ARRAY, parser.next()); + assertEquals(JsonParser.Event.END_ARRAY, parser.next()); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + assertEquals(JsonParser.Event.START_OBJECT, parser.next()); + parser.skipObject(); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + assertEquals(JsonParser.Event.VALUE_NUMBER, parser.next()); + assertEquals(JsonParser.Event.END_OBJECT, parser.next()); + assertEquals(false, parser.hasNext()); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonParserTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonParserTest.java new file mode 100644 index 0000000..ed5d6c9 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonParserTest.java
@@ -0,0 +1,827 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import junit.framework.TestCase; + +import jakarta.json.*; +import jakarta.json.stream.JsonLocation; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import jakarta.json.stream.JsonParserFactory; +import java.math.BigDecimal; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.Scanner; +import jakarta.json.stream.JsonParsingException; + +import org.glassfish.json.api.BufferPool; + +/** + * JsonParser Tests + * + * @author Jitendra Kotamraju + */ +public class JsonParserTest extends TestCase { + static final Charset UTF_32LE = Charset.forName("UTF-32LE"); + static final Charset UTF_32BE = Charset.forName("UTF-32BE"); + + public JsonParserTest(String testName) { + super(testName); + } + + public void testReader() { + JsonParser reader = Json.createParser( + new StringReader("{ \"a\" : \"b\", \"c\" : null, \"d\" : [null, \"abc\"] }")); + reader.close(); + } + + + public void testEmptyArrayReader() { + try (JsonParser parser = Json.createParser(new StringReader("[]"))) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStream() { + try (JsonParser parser = Json.createParser( + new ByteArrayInputStream(new byte[]{'[', ']'}))) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStreamUTF8() { + ByteArrayInputStream bin = new ByteArrayInputStream("[]".getBytes(StandardCharsets.UTF_8)); + try (JsonParser parser = Json.createParser(bin)) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStreamUTF16LE() { + ByteArrayInputStream bin = new ByteArrayInputStream("[]".getBytes(StandardCharsets.UTF_16LE)); + try (JsonParser parser = Json.createParser(bin)) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStreamUTF16BE() { + ByteArrayInputStream bin = new ByteArrayInputStream("[]".getBytes(StandardCharsets.UTF_16BE)); + try (JsonParser parser = Json.createParser(bin)) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStreamUTF32LE() { + ByteArrayInputStream bin = new ByteArrayInputStream("[]".getBytes(UTF_32LE)); + try (JsonParser parser = Json.createParser(bin)) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStreamUTF32BE() { + ByteArrayInputStream bin = new ByteArrayInputStream("[]".getBytes(UTF_32BE)); + try (JsonParser parser = Json.createParser(bin)) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStreamUTF16() { + ByteArrayInputStream bin = new ByteArrayInputStream("[]".getBytes(StandardCharsets.UTF_16)); + try (JsonParser parser = Json.createParser(bin)) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStreamWithConfig() { + Map<String, ?> config = new HashMap<>(); + try (JsonParser parser = Json.createParserFactory(config).createParser( + new ByteArrayInputStream(new byte[]{'[', ']'}))) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStructure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createArrayBuilder().build())) { + testEmptyArray(parser); + } + } + + public void testEmptyArrayStructureWithConfig() { + Map<String, ?> config = new HashMap<>(); + try (JsonParser parser = Json.createParserFactory(config).createParser( + Json.createArrayBuilder().build())) { + testEmptyArray(parser); + } + } + + @SuppressWarnings("UnusedDeclaration") + static void testEmptyArray(JsonParser parser) { + while (parser.hasNext()) { + parser.next(); + } + } + + + public void testEmptyArrayReaderIterator() { + try (JsonParser parser = Json.createParser(new StringReader("[]"))) { + testEmptyArrayIterator(parser); + } + } + + public void testEmptyArrayStructureIterator() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createArrayBuilder().build())) { + testEmptyArrayIterator(parser); + } + } + + static void testEmptyArrayIterator(JsonParser parser) { + assertEquals(true, parser.hasNext()); + assertEquals(true, parser.hasNext()); + assertEquals(Event.START_ARRAY, parser.next()); + + assertEquals(true, parser.hasNext()); + assertEquals(true, parser.hasNext()); + assertEquals(Event.END_ARRAY, parser.next()); + + assertEquals(false, parser.hasNext()); + assertEquals(false, parser.hasNext()); + try { + parser.next(); + fail("Should have thrown a NoSuchElementException"); + } catch (NoSuchElementException ne) { + } + } + + + public void testEmptyArrayIterator2Reader() { + try (JsonParser parser = Json.createParser(new StringReader("[]"))) { + testEmptyArrayIterator2(parser); + } + } + + public void testEmptyArrayIterator2Structure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createArrayBuilder().build())) { + testEmptyArrayIterator2(parser); + } + } + + static void testEmptyArrayIterator2(JsonParser parser) { + assertEquals(Event.START_ARRAY, parser.next()); + assertEquals(Event.END_ARRAY, parser.next()); + try { + parser.next(); + fail("Should have thrown a NoSuchElementException"); + } catch (NoSuchElementException ne) { + } + } + + public void testEmptyArrayIterator3Reader() { + try (JsonParser parser = Json.createParser(new StringReader("[]"))) { + testEmptyArrayIterator3(parser); + } + } + + public void testEmptyArrayIterator3Structure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createArrayBuilder().build())) { + testEmptyArrayIterator3(parser); + } + } + + static void testEmptyArrayIterator3(JsonParser parser) { + assertEquals(Event.START_ARRAY, parser.next()); + assertEquals(Event.END_ARRAY, parser.next()); + assertEquals(false, parser.hasNext()); + try { + parser.next(); + fail("Should have thrown a NoSuchElementException"); + } catch (NoSuchElementException ne) { + } + } + + + // Tests empty object + public void testEmptyObjectReader() { + try (JsonParser parser = Json.createParser(new StringReader("{}"))) { + testEmptyObject(parser); + } + } + + public void testEmptyObjectStream() { + try (JsonParser parser = Json.createParser( + new ByteArrayInputStream(new byte[]{'{', '}'}))) { + testEmptyObject(parser); + } + } + + public void testEmptyObjectStructure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createObjectBuilder().build())) { + testEmptyObject(parser); + } + } + + public void testEmptyObjectStructureWithConfig() { + Map<String, ?> config = new HashMap<>(); + try (JsonParser parser = Json.createParserFactory(config).createParser( + Json.createObjectBuilder().build())) { + testEmptyObject(parser); + } + } + + @SuppressWarnings("UnusedDeclaration") + static void testEmptyObject(JsonParser parser) { + while (parser.hasNext()) { + parser.next(); + } + } + + + public void testEmptyObjectIteratorReader() { + try (JsonParser parser = Json.createParser(new StringReader("{}"))) { + testEmptyObjectIterator(parser); + } + } + + public void testEmptyObjectIteratorStructure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createObjectBuilder().build())) { + testEmptyObjectIterator(parser); + } + } + + static void testEmptyObjectIterator(JsonParser parser) { + assertEquals(true, parser.hasNext()); + assertEquals(true, parser.hasNext()); + assertEquals(Event.START_OBJECT, parser.next()); + + assertEquals(true, parser.hasNext()); + assertEquals(true, parser.hasNext()); + assertEquals(Event.END_OBJECT, parser.next()); + + assertEquals(false, parser.hasNext()); + assertEquals(false, parser.hasNext()); + try { + parser.next(); + fail("Should have thrown a NoSuchElementException"); + } catch (NoSuchElementException ne) { + } + } + + + public void testEmptyObjectIterator2Reader() { + try (JsonParser parser = Json.createParser(new StringReader("{}"))) { + testEmptyObjectIterator2(parser); + } + } + + public void testEmptyObjectIterator2Structure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createObjectBuilder().build())) { + testEmptyObjectIterator2(parser); + } + } + + static void testEmptyObjectIterator2(JsonParser parser) { + assertEquals(Event.START_OBJECT, parser.next()); + assertEquals(Event.END_OBJECT, parser.next()); + try { + parser.next(); + fail("Should have thrown a NoSuchElementException"); + } catch (NoSuchElementException ne) { + } + } + + + public void testEmptyObjectIterator3Reader() { + try (JsonParser parser = Json.createParser(new StringReader("{}"))) { + testEmptyObjectIterator3(parser); + } + } + + public void testEmptyObjectIterator3Structure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createObjectBuilder().build())) { + testEmptyObjectIterator3(parser); + } + } + + static void testEmptyObjectIterator3(JsonParser parser) { + assertEquals(Event.START_OBJECT, parser.next()); + assertEquals(Event.END_OBJECT, parser.next()); + assertEquals(false, parser.hasNext()); + try { + parser.next(); + fail("Should have thrown a NoSuchElementException"); + } catch (NoSuchElementException ne) { + // expected + } + } + + + public void testWikiIteratorReader() throws Exception { + try (JsonParser parser = Json.createParser(wikiReader())) { + testWikiIterator(parser); + } + } + + public void testWikiIteratorStructure() throws Exception { + try (JsonParser parser = Json.createParserFactory(null).createParser( + JsonBuilderTest.buildPerson())) { + testWikiIterator(parser); + } + } + + @SuppressWarnings("UnusedDeclaration") + static void testWikiIterator(JsonParser parser) throws Exception { + while (parser.hasNext()) { + parser.next(); + } + } + + public void testWikiInputStream() throws Exception { + try (JsonParser parser = Json.createParser(wikiStream())) { + testWiki(parser); + } + } + + public void testWikiInputStreamUTF16LE() throws Exception { + ByteArrayInputStream bin = new ByteArrayInputStream(wikiString() + .getBytes(StandardCharsets.UTF_16LE)); + try (JsonParser parser = Json.createParser(bin)) { + testWiki(parser); + } + } + + public void testWikiReader() throws Exception { + try (JsonParser parser = Json.createParser(wikiReader())) { + testWiki(parser); + } + } + + public void testWikiStructure() throws Exception { + try (JsonParser parser = Json.createParserFactory(null).createParser( + JsonBuilderTest.buildPerson())) { + testWiki(parser); + } + } + + static void testWiki(JsonParser parser) { + + Event event = parser.next(); + assertEquals(Event.START_OBJECT, event); + + testObjectStringValue(parser, "firstName", "John"); + testObjectStringValue(parser, "lastName", "Smith"); + + event = parser.next(); + assertEquals(Event.KEY_NAME, event); + assertEquals("age", parser.getString()); + + event = parser.next(); + assertEquals(Event.VALUE_NUMBER, event); + assertEquals(25, parser.getInt()); + assertEquals(25, parser.getLong()); + assertEquals(25, parser.getBigDecimal().intValue()); + assertTrue( parser.isIntegralNumber()); + + event = parser.next(); + assertEquals(Event.KEY_NAME, event); + assertEquals("address", parser.getString()); + + event = parser.next(); + assertEquals(Event.START_OBJECT, event); + + + testObjectStringValue(parser, "streetAddress", "21 2nd Street"); + testObjectStringValue(parser, "city", "New York"); + testObjectStringValue(parser, "state", "NY"); + testObjectStringValue(parser, "postalCode", "10021"); + + event = parser.next(); + assertEquals(Event.END_OBJECT, event); + + event = parser.next(); + assertEquals(Event.KEY_NAME, event); + assertEquals("phoneNumber", parser.getString()); + + event = parser.next(); + assertEquals(Event.START_ARRAY, event); + event = parser.next(); + assertEquals(Event.START_OBJECT, event); + testObjectStringValue(parser, "type", "home"); + testObjectStringValue(parser, "number", "212 555-1234"); + event = parser.next(); + assertEquals(Event.END_OBJECT, event); + + event = parser.next(); + assertEquals(Event.START_OBJECT, event); + testObjectStringValue(parser, "type", "fax"); + testObjectStringValue(parser, "number", "646 555-4567"); + event = parser.next(); + assertEquals(Event.END_OBJECT, event); + event = parser.next(); + assertEquals(Event.END_ARRAY, event); + + event = parser.next(); + assertEquals(Event.END_OBJECT, event); + } + + static void testObjectStringValue(JsonParser parser, String name, String value) { + Event event = parser.next(); + assertEquals(Event.KEY_NAME, event); + assertEquals(name, parser.getString()); + + event = parser.next(); + assertEquals(Event.VALUE_STRING, event); + assertEquals(value, parser.getString()); + } + + public void testNestedArrayReader() { + try (JsonParser parser = Json.createParser(new StringReader("[[],[[]]]"))) { + testNestedArray(parser); + } + } + + public void testNestedArrayStructure() { + try (JsonParser parser = Json.createParserFactory(null).createParser( + Json.createArrayBuilder() + .add(Json.createArrayBuilder()) + .add(Json.createArrayBuilder() + .add(Json.createArrayBuilder())) + .build())) { + testNestedArray(parser); + } + } + + static void testNestedArray(JsonParser parser) { + assertEquals(Event.START_ARRAY, parser.next()); + assertEquals(Event.START_ARRAY, parser.next()); + assertEquals(Event.END_ARRAY, parser.next()); + assertEquals(Event.START_ARRAY, parser.next()); + assertEquals(Event.START_ARRAY, parser.next()); + assertEquals(Event.END_ARRAY, parser.next()); + assertEquals(Event.END_ARRAY, parser.next()); + assertEquals(Event.END_ARRAY, parser.next()); + assertEquals(false, parser.hasNext()); + assertEquals(false, parser.hasNext()); + } + + public void testExceptionsReader() throws Exception { + try (JsonParser parser = Json.createParser(wikiReader())) { + testExceptions(parser); + } + } + + public void testExceptionsStructure() throws Exception { + try (JsonParser parser = Json.createParserFactory(null).createParser( + JsonBuilderTest.buildPerson())) { + testExceptions(parser); + } + } + + static void testExceptions(JsonParser parser) { + + Event event = parser.next(); + assertEquals(Event.START_OBJECT, event); + + try { + parser.getString(); + fail("JsonParser#getString() should have thrown exception in START_OBJECT state"); + } catch (IllegalStateException expected) { + // no-op + } + + try { + parser.isIntegralNumber(); + fail("JsonParser#getNumberType() should have thrown exception in START_OBJECT state"); + } catch (IllegalStateException expected) { + // no-op + } + + try { + parser.getInt(); + fail("JsonParser#getInt() should have thrown exception in START_OBJECT state"); + } catch (IllegalStateException expected) { + // no-op + } + + try { + parser.getLong(); + fail("JsonParser#getLong() should have thrown exception in START_OBJECT state"); + } catch (IllegalStateException expected) { + // no-op + } + + try { + parser.getBigDecimal(); + fail("JsonParser#getBigDecimal() should have thrown exception in START_OBJECT state"); + } catch (IllegalStateException expected) { + // no-op + } + } + + static String wikiString() { + String str; + try (Scanner scanner = new Scanner(wikiReader()) + .useDelimiter("\\A")) { + str = scanner.hasNext() ? scanner.next() : ""; + } + return str; + } + + static InputStream wikiStream() { + return JsonParserTest.class.getResourceAsStream("/wiki.json"); + } + + static Reader wikiReader() { + return new InputStreamReader( + JsonParserTest.class.getResourceAsStream("/wiki.json"), StandardCharsets.UTF_8); + } + + public void testIntNumber() { + JsonParserFactory factory = Json.createParserFactory(null); + + Random r = new Random(System.currentTimeMillis()); + + for(int i=0; i < 100000; i++) { + long num = i%2 == 0 ? r.nextInt() : r.nextLong(); + try (JsonParser parser = factory.createParser(new StringReader("["+num+"]"))) { + parser.next(); + parser.next(); + assertEquals("Fails for num="+num, new BigDecimal(num).intValue(), parser.getInt()); + } + } + + } + + public void testBigDecimalGetString() { + JsonParserFactory f = Json.createParserFactory(null); + JsonObject obj = Json.createObjectBuilder().add("a", BigDecimal.ONE).build(); + try (JsonParser parser = f.createParser(obj)) { + parser.next(); + parser.next(); + parser.next(); + assertEquals("Fails for BigDecimal=1", "1", parser.getString()); + } + } + + public void testIntGetString() { + JsonParserFactory f = Json.createParserFactory(null); + JsonObject obj = Json.createObjectBuilder().add("a", 5).build(); + try (JsonParser parser = f.createParser(obj)) { + parser.next(); + parser.next(); + parser.next(); + assertEquals("Fails for int=5", "5", parser.getString()); + } + } + static class MyBufferPool implements BufferPool { + private boolean takeCalled; + private boolean recycleCalled; + private final char[] buf; + + MyBufferPool(int size) { + buf = new char[size]; + } + + @Override + public char[] take() { + takeCalled = true; + return buf; + } + + @Override + public void recycle(char[] buf) { + recycleCalled = true; + } + + boolean isTakeCalled() { + return takeCalled; + } + + boolean isRecycleCalled() { + return recycleCalled; + } + } + + public void testBufferPoolFeature() { + final MyBufferPool bufferPool = new MyBufferPool(1024); + Map<String, Object> config = new HashMap<String, Object>() {{ + put(BufferPool.class.getName(), bufferPool); + }}; + + JsonParserFactory factory = Json.createParserFactory(config); + try (JsonParser parser = factory.createParser(new StringReader("[]"))) { + parser.next(); + parser.next(); + } + assertTrue(bufferPool.isTakeCalled()); + assertTrue(bufferPool.isRecycleCalled()); + } + + public void testBufferSizes() { + Random r = new Random(System.currentTimeMillis()); + for(int size=100; size < 1000; size++) { + final MyBufferPool bufferPool = new MyBufferPool(size); + Map<String, Object> config = new HashMap<String, Object>() {{ + put(BufferPool.class.getName(), bufferPool); + }}; + JsonParserFactory factory = Json.createParserFactory(config); + + StringBuilder sb = new StringBuilder(); + for(int i=0; i < 1000; i++) { + sb.append('a'); + String name = sb.toString(); + long num = i%2 == 0 ? r.nextInt() : r.nextLong(); + String str = "{\""+name+"\":["+num+"]}"; + try (JsonParser parser = factory.createParser(new StringReader(str))) { + parser.next(); + parser.next(); + assertEquals("Fails for " + str, name, parser.getString()); + parser.next(); + parser.next(); + assertEquals("Fails for "+str, new BigDecimal(num).intValue(), parser.getInt()); + } + } + } + } + + // Tests for string starting on buffer boundary (JSONP-15) + // xxxxxxx"xxxxxxxxx" + // ^ + // | + // 4096 + public void testStringUsingStandardBuffer() throws Throwable { + JsonParserFactory factory = Json.createParserFactory(null); + StringBuilder sb = new StringBuilder(); + for(int i=0; i < 40000; i++) { + sb.append('a'); + String name = sb.toString(); + String str = "{\""+name+"\":\""+name+"\"}"; + try (JsonParser parser = factory.createParser(new StringReader(str))) { + parser.next(); + parser.next(); + assertEquals("Fails for size=" + i, name, parser.getString()); + parser.next(); + assertEquals("Fails for size=" + i, name, parser.getString()); + } catch (Throwable e) { + throw new Throwable("Failed for size=" + i, e); + } + } + } + + // Tests for int starting on buffer boundary + // xxxxxxx"xxxxxxxxx" + // ^ + // | + // 4096 + public void testIntegerUsingStandardBuffer() throws Throwable { + Random r = new Random(System.currentTimeMillis()); + JsonParserFactory factory = Json.createParserFactory(null); + StringBuilder sb = new StringBuilder(); + for(int i=0; i < 40000; i++) { + sb.append('a'); + String name = sb.toString(); + int num = r.nextInt(); + String str = "{\"" + name + "\":" + num + "}"; + try (JsonParser parser = factory.createParser(new StringReader(str))) { + parser.next(); + parser.next(); + assertEquals("Fails for size=" + i, name, parser.getString()); + parser.next(); + assertEquals("Fails for size=" + i, num, parser.getInt()); + } catch (Throwable e) { + throw new Throwable("Failed for size=" + i, e); + } + } + } + + public void testStringUsingBuffers() throws Throwable { + for(int size=20; size < 500; size++) { + final MyBufferPool bufferPool = new MyBufferPool(size); + Map<String, Object> config = new HashMap<String, Object>() {{ + put(BufferPool.class.getName(), bufferPool); + }}; + JsonParserFactory factory = Json.createParserFactory(config); + + StringBuilder sb = new StringBuilder(); + for(int i=0; i < 1000; i++) { + sb.append('a'); + String name = sb.toString(); + String str = "{\""+name+"\":\""+name+"\"}"; + JsonLocation location; + try (JsonParser parser = factory.createParser(new StringReader(str))) { + parser.next(); + parser.next(); + assertEquals("name fails for buffer size=" + size + " name length=" + i, name, parser.getString()); + location = parser.getLocation(); + assertEquals("Stream offset fails for buffer size=" + size + " name length=" + i, + name.length() + 3, location.getStreamOffset()); + assertEquals("Column value fails for buffer size=" + size + " name length=" + i, + name.length() + 4, location.getColumnNumber()); + assertEquals("Line value fails for buffer size=" + size + " name length=" + i, + 1, location.getLineNumber()); + + parser.next(); + assertEquals("value fails for buffer size=" + size + " name length=" + i, name, parser.getString()); + location = parser.getLocation(); + assertEquals("Stream offset fails for buffer size=" + size + " name length=" + i, 2 * name.length() + 6, location.getStreamOffset()); + assertEquals("Column value fails for buffer size=" + size + " name length=" + i, + 2 * name.length() + 7, location.getColumnNumber()); + assertEquals("Line value fails for buffer size=" + size + " name length=" + i, + 1, location.getLineNumber()); + } catch (Throwable e) { + throw new Throwable("Failed for buffer size=" + size + " name length=" + i, e); + } + } + } + } + + public void testExceptionsFromHasNext() { + checkExceptionFromHasNext("{"); + checkExceptionFromHasNext("{\"key\""); + checkExceptionFromHasNext("{\"name\" : \"prop\""); + checkExceptionFromHasNext("{\"name\" : 3"); + checkExceptionFromHasNext("{\"name\" : true"); + checkExceptionFromHasNext("{\"name\" : null"); + checkExceptionFromHasNext("{\"name\" : {\"$eq\":\"cdc\"}"); + checkExceptionFromHasNext("{\"name\" : [{\"$eq\":\"cdc\"}]"); + checkExceptionFromHasNext("["); + checkExceptionFromHasNext("{\"name\" : [{\"key\" : [[{\"a\" : 1}]"); + checkExceptionFromHasNext("{\"unique\":true,\"name\":\"jUnitTestIndexNeg005\", \"fields\":[{\"order\":-1,\"path\":\"city.zip\"}"); + } + + public void testEOFFromHasNext() { + checkExceptionFromHasNext("{ \"d\" : 1 } 2 3 4"); + checkExceptionFromHasNext("[ {\"d\" : 1 }] 2 3 4"); + checkExceptionFromHasNext("1 2 3 4"); + checkExceptionFromHasNext("null 2 3 4"); + } + + public void testExceptionsFromNext() { + checkExceptionFromNext("{\"name\" : fal"); + checkExceptionFromNext("{\"name\" : nu"); + checkExceptionFromNext("{\"name\" : \"pro"); + checkExceptionFromNext("{\"key\":"); + checkExceptionFromNext("fal"); + } + + private void checkExceptionFromHasNext(String input) { + try (JsonParser parser = Json.createParser(new StringReader(input))) { + try { + while (parser.hasNext()) { + try { + parser.next(); + } catch (Throwable t1) { + fail("Exception should occur from hasNext() for '" + input + "'"); + } + } + } catch (JsonParsingException t) { + //this is OK + return; + } + } + fail(); + } + + private void checkExceptionFromNext(String input) { + try (JsonParser parser = Json.createParser(new StringReader(input))) { + while (parser.hasNext()) { + try { + parser.next(); + } catch (JsonParsingException t) { + //this is OK + return; + } + } + } + fail(); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonParsingExceptionTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonParsingExceptionTest.java new file mode 100644 index 0000000..425ca52 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonParsingExceptionTest.java
@@ -0,0 +1,155 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.Json; +import jakarta.json.stream.JsonLocation; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParsingException; +import java.io.StringReader; + +/** + * JsonParsingException Tests + * + * @author Jitendra Kotamraju + */ +public class JsonParsingExceptionTest extends TestCase { + + public void testWrongJson() { + // testMalformedJson("", null); Allowed in 1.1 + } + + public void testWrongJson1() { + // testMalformedJson("{}{}", null); Allowed in 1.1 + } + + public void testWrongJson2() { + // testMalformedJson("{", null); Allowed in 1.1 + } + + public void testWrongJson3() { + testMalformedJson("{[]", null); + } + + public void testWrongJson4() { + testMalformedJson("{]", null); + } + + public void testWrongJson5() { + testMalformedJson("{\"a\":[]]", null); + } + + public void testWrongJson6() { + testMalformedJson("[ {}, [] }", null); + } + + public void testWrongJson61() { + testMalformedJson("[ {}, {} }", null); + } + + public void testWrongJson7() { + testMalformedJson("{ \"a\" : {}, \"b\": {} ]", null); + } + + public void testWrongJson8() { + testMalformedJson("{ \"a\" : {}, \"b\": [] ]", null); + } + + public void testWrongUnicode() { + testMalformedJson("[ \"\\uX00F\" ]", null); + testMalformedJson("[ \"\\u000Z\" ]", null); + testMalformedJson("[ \"\\u000\" ]", null); + testMalformedJson("[ \"\\u00\" ]", null); + testMalformedJson("[ \"\\u0\" ]", null); + testMalformedJson("[ \"\\u\" ]", null); + testMalformedJson("[ \"\\u\"", null); + testMalformedJson("[ \"\\", null); + } + + public void testControlChar() { + testMalformedJson("[ \"\u0000\" ]", null); + testMalformedJson("[ \"\u000c\" ]", null); + testMalformedJson("[ \"\u000f\" ]", null); + testMalformedJson("[ \"\u001F\" ]", null); + testMalformedJson("[ \"\u001f\" ]", null); + } + + public void testLocation1() { + testMalformedJson("x", new MyLocation(1, 1, 0)); + testMalformedJson("{]", new MyLocation(1, 2, 1)); + testMalformedJson("[}", new MyLocation(1, 2, 1)); + testMalformedJson("[a", new MyLocation(1, 2, 1)); + testMalformedJson("[nuLl]", new MyLocation(1, 4, 3)); + testMalformedJson("[falsE]", new MyLocation(1, 6, 5)); + // testMalformedJson("[][]", new MyLocation(1, 3, 2)); allowed in 1.1 + testMalformedJson("[1234L]", new MyLocation(1, 6, 5)); + } + + public void testLocation2() { + testMalformedJson("[null\n}", new MyLocation(2, 1, 6)); + testMalformedJson("[null\r\n}", new MyLocation(2, 1, 7)); + testMalformedJson("[null\n, null\n}", new MyLocation(3, 1, 13)); + testMalformedJson("[null\r\n, null\r\n}", new MyLocation(3, 1, 15)); + } + + private void testMalformedJson(String json, JsonLocation expected) { + try (JsonParser parser = Json.createParser(new StringReader(json))) { + while (parser.hasNext()) { + parser.next(); + } + fail("Expected to throw JsonParsingException for " + json); + } catch (JsonParsingException je) { + // Expected + if (expected != null) { + JsonLocation got = je.getLocation(); + assertEquals(expected.getLineNumber(), got.getLineNumber()); + assertEquals(expected.getColumnNumber(), got.getColumnNumber()); + assertEquals(expected.getStreamOffset(), got.getStreamOffset()); + } + } + } + + private static class MyLocation implements JsonLocation { + private final long columnNo; + private final long lineNo; + private final long streamOffset; + + MyLocation(long lineNo, long columnNo, long streamOffset) { + this.lineNo = lineNo; + this.columnNo = columnNo; + this.streamOffset = streamOffset; + } + + @Override + public long getLineNumber() { + return lineNo; + } + + @Override + public long getColumnNumber() { + return columnNo; + } + + @Override + public long getStreamOffset() { + return streamOffset; + } + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPatchBugsTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPatchBugsTest.java new file mode 100644 index 0000000..5ba3b92 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPatchBugsTest.java
@@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonPatch; +import jakarta.json.JsonReader; +import jakarta.json.JsonStructure; + +import java.io.StringReader; + +import org.junit.Test; + +/** + * + * @author lukas + */ +public class JsonPatchBugsTest { + + // https://github.com/javaee/jsonp/issues/58 + @Test(expected = JsonException.class) + public void applyThrowsJsonException() { + JsonArray array = Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("name", "Bob") + .build()) + .build(); + JsonPatch patch = Json.createPatchBuilder() + .replace("/0/name", "Bobek") + .replace("/1/name", "Vila Amalka") + .build(); + JsonArray result = patch.apply(array); + } + + // https://github.com/eclipse-ee4j/jsonp/issues/181 + @Test(expected = JsonException.class) + public void applyThrowsJsonException2() { + // JSON document to be patched + String targetDocument + = "{\n" + + " \"firstName\": \"John\",\n" + + " \"lastName\": \"Doe\"\n" + + "}"; + + // JSON Patch document + // Instead of "op", we have "op_", which is invalid + String patchDocument + = "[\n" + + " { \"op_\": \"replace\", \"path\": \"/firstName\", \"value\": \"Jane\" }\n" + + "]"; + + try (JsonReader objectReader = Json.createReader(new StringReader(targetDocument)); + JsonReader arrayReader = Json.createReader(new StringReader(patchDocument))) { + + JsonStructure target = objectReader.read(); + JsonPatch patch = Json.createPatch(arrayReader.readArray()); + + // Applies the patch + // It will throw a NullPointerException with no message + JsonStructure patched = patch.apply(target); + } + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPatchBuilderTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPatchBuilderTest.java new file mode 100644 index 0000000..ded202f --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPatchBuilderTest.java
@@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatchBuilder; + +import org.junit.Test; + +/** + * + * @author Alex Soto + * + */ +public class JsonPatchBuilderTest { + + @Test + public void shouldBuildJsonPatchExpressionUsingJsonPatchBuilder() { + JsonPatchBuilder patchBuilder = Json.createPatchBuilder(); + JsonObject result = patchBuilder.add("/email", "john@example.com") + .replace("/age", 30) + .remove("/phoneNumber") + .test("/firstName", "John") + .copy("/address/lastName", "/lastName") + .build() + .apply(buildPerson()); + assertThat(result, is(expectedBuildPerson())); + + } + + static JsonObject expectedBuildPerson() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("email", "john@example.com") + .add("age", 30) + .add("address", Json.createObjectBuilder() + .add("lastName", "Smith") + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .build(); + } + + static JsonObject buildPerson() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPatchDiffTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPatchDiffTest.java new file mode 100644 index 0000000..4743b68 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPatchDiffTest.java
@@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatch; +import jakarta.json.JsonReader; +import jakarta.json.JsonString; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * + * @author Alex Soto + * + */ +@RunWith(Parameterized.class) +public class JsonPatchDiffTest { + + @Parameters(name = "{index}: ({0})={1}") + public static Iterable<Object[]> data() throws Exception { + List<Object[]> examples = new ArrayList<>(); + JsonArray data = JsonPatchDiffTest.loadData(); + for (JsonValue jsonValue : data) { + JsonObject test = (JsonObject) jsonValue; + Object[] testData = new Object[4]; + testData[0] = test.get("original"); + testData[1] = test.get("target"); + testData[2] = test.get("expected"); + testData[3] = createExceptionClass((JsonString)test.get("exception")); + + examples.add(testData); + } + + return examples; + } + + private static Class<? extends Exception> createExceptionClass( + JsonString exceptionClassName) throws ClassNotFoundException { + if (exceptionClassName != null) { + return (Class<? extends Exception>) Class + .forName(exceptionClassName.getString()); + } + return null; + } + + private static JsonArray loadData() { + InputStream testData = JsonPatchTest.class + .getResourceAsStream("/jsonpatchdiff.json"); + + JsonArray data; + try(JsonReader reader = Json.createReader(testData)){ + data = (JsonArray) reader.read(); + } + + return data; + } + + private JsonStructure original; + private JsonStructure target; + private JsonValue expected; + private Class<? extends Exception> expectedException; + + public JsonPatchDiffTest(JsonStructure original, JsonStructure target, + JsonValue expected, Class<? extends Exception> expectedException) { + super(); + this.original = original; + this.target = target; + this.expected = expected; + this.expectedException = expectedException; + } + + @Test + public void shouldExecuteJsonPatchDiffOperationsToJsonDocument() { + try { + JsonPatch diff = Json.createDiff(this.original, this.target); + assertThat(diff, is(Json.createPatchBuilder((JsonArray) expected).build())); + assertThat(expectedException, nullValue()); + } catch (Exception e) { + if (expectedException == null) { + fail(e.getMessage()); + } else { + assertThat(e, instanceOf(expectedException)); + } + } + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPatchOperationTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPatchOperationTest.java new file mode 100644 index 0000000..0742cbb --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPatchOperationTest.java
@@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import jakarta.json.JsonException; +import jakarta.json.JsonPatch.Operation; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author lukas + */ +public class JsonPatchOperationTest { + + private static final String[] opNames = {"add", "remove", "replace", "move", "copy", "test"}; + + @Test + public void fromOperationName() { + for (String op: opNames) { + Assert.assertEquals(Operation.valueOf(op.toUpperCase()), Operation.fromOperationName(op)); + } + for (String op: opNames) { + Assert.assertEquals(Operation.valueOf(op.toUpperCase()), Operation.fromOperationName(op.toUpperCase())); + } + } + + @Test(expected = JsonException.class) + public void fromInvalidOperationName() { + Operation.fromOperationName("undef"); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPatchTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPatchTest.java new file mode 100644 index 0000000..08f3004 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPatchTest.java
@@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatch; +import jakarta.json.JsonReader; +import jakarta.json.JsonString; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * + * @author Alex Soto + * + */ +@RunWith(Parameterized.class) +public class JsonPatchTest { + + @Parameters(name = "{index}: ({0})={1}") + public static Iterable<Object[]> data() throws Exception { + List<Object[]> examples = new ArrayList<>(); + JsonArray data = loadData(); + for (JsonValue jsonValue : data) { + JsonObject test = (JsonObject) jsonValue; + Object[] testData = new Object[4]; + testData[0] = createPatchArray(test.get("op")); + testData[1] = test.get("target"); + testData[2] = test.get("expected"); + testData[3] = createExceptionClass((JsonString)test.get("exception")); + + examples.add(testData); + } + + return examples; + } + + private static Class<? extends Exception> createExceptionClass( + JsonString exceptionClassName) throws ClassNotFoundException { + if (exceptionClassName != null) { + return (Class<? extends Exception>) Class + .forName(exceptionClassName.getString()); + } + return null; + } + + private static JsonArray createPatchArray(JsonValue object) { + return Json.createArrayBuilder().add(object).build(); + } + + private static JsonArray loadData() { + InputStream testData = JsonPatchTest.class + .getResourceAsStream("/jsonpatch.json"); + JsonReader reader = Json.createReader(testData); + return (JsonArray) reader.read(); + } + + private JsonArray patch; + private JsonStructure target; + private JsonValue expected; + private Class<? extends Exception> expectedException; + + public JsonPatchTest(JsonArray patch, JsonStructure target, + JsonValue expected, Class<? extends Exception> expectedException) { + super(); + this.patch = patch; + this.target = target; + this.expected = expected; + this.expectedException = expectedException; + } + + @Test + public void shouldExecuteJsonPatchOperationsToJsonDocument() { + try { + JsonPatch patch = Json.createPatchBuilder(this.patch).build(); + JsonStructure output = patch.apply(target); + assertThat(output, is(expected)); + assertThat(expectedException, nullValue()); + } catch (Exception e) { + if (expectedException == null) { + fail(e.getMessage()); + } else { + assertThat(e, instanceOf(expectedException)); + } + } + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPointerAddOperationTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPointerAddOperationTest.java new file mode 100644 index 0000000..5fe2fe6 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPointerAddOperationTest.java
@@ -0,0 +1,203 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.Arrays; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * + * @author Alex Soto + * + */ +@RunWith(Parameterized.class) +public class JsonPointerAddOperationTest { + + @Parameters(name = "{index}: ({0})={1}") + public static Iterable<Object[]> data() throws Exception { + return Arrays.asList(new Object[][] { + {buildSimpleAddPatch(), buildAddress(), buildExpectedAddress() }, + {buildComplexAddPatch(), buildPerson(), buildExpectedPerson()}, + {buildArrayAddPatchInPosition(), buildPerson(), buildExpectedPersonConcreteArrayPosition()}, + {buildArrayAddPatchInLastPosition(), buildPerson(), buildExpectedPersonArrayLastPosition()} + }); + } + + private JsonObject pathOperation; + private JsonStructure target; + private JsonValue expectedResult; + + public JsonPointerAddOperationTest(JsonObject pathOperation, + JsonStructure target, JsonValue expectedResult) { + super(); + this.pathOperation = pathOperation; + this.target = target; + this.expectedResult = expectedResult; + } + + @Test + public void shouldAddElementsToExistingJsonDocument() { + JsonPointer pointer = Json.createPointer(pathOperation.getString("path")); + JsonObject modified = (JsonObject) pointer.add(target, pathOperation.get("value")); + assertThat(modified, is(expectedResult)); + } + + static JsonObject buildAddress() { + return Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021") + .build(); + } + static JsonObject buildComplexAddPatch() { + return Json.createObjectBuilder() + .add("op", "add") + .add("path", "/address/streetAddress") + .add("value", "myaddress") + .build(); + } + static JsonObject buildSimpleAddPatch() { + return Json.createObjectBuilder() + .add("op", "add") + .add("path", "/streetAddress") + .add("value", "myaddress") + .build(); + } + static JsonObject buildArrayAddPatchInPosition() { + return Json.createObjectBuilder() + .add("op", "add") + .add("path", "/phoneNumber/0") + .add("value", Json.createObjectBuilder() + .add("type", "home") + .add("number", "200 555-1234")) + .build(); + } + static JsonObject buildArrayAddPatchInLastPosition() { + return Json.createObjectBuilder() + .add("op", "add") + .add("path", "/phoneNumber/-") + .add("value", Json.createObjectBuilder() + .add("type", "home") + .add("number", "200 555-1234")) + .build(); + } + static JsonObject buildExpectedAddress() { + return Json.createObjectBuilder() + .add("streetAddress", "myaddress") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021") + .build(); + } + static JsonObject buildPerson() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + static JsonObject buildExpectedPersonConcreteArrayPosition() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add((Json.createObjectBuilder() + .add("type", "home") + .add("number", "200 555-1234"))) + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + static JsonObject buildExpectedPersonArrayLastPosition() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567")) + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "200 555-1234"))) + .build(); + } + static JsonObject buildExpectedPerson() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "myaddress") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPointerEscapeTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPointerEscapeTest.java new file mode 100644 index 0000000..904d405 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPointerEscapeTest.java
@@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import org.junit.Test; + +import jakarta.json.Json; + +import static org.junit.Assert.assertEquals; + +/** + * JSON pointer escape/unescape tests. + * + * @author Dmitry Kornilov + */ +public class JsonPointerEscapeTest { + + @Test + public void escapeTest() { + assertEquals("a~1b", Json.encodePointer("a/b")); + assertEquals("a~0b~1c", Json.encodePointer("a~b/c")); + } + + @Test + public void unescapeTest() { + assertEquals("/a/b", Json.decodePointer("/a~1b")); + assertEquals("/~1", Json.decodePointer("/~01")); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPointerRemoveOperationTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPointerRemoveOperationTest.java new file mode 100644 index 0000000..1211261 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPointerRemoveOperationTest.java
@@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.Arrays; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * + * @author Alex Soto + * + */ +@RunWith(Parameterized.class) +public class JsonPointerRemoveOperationTest { + + @Parameters(name = "{index}: ({0})={1}") + public static Iterable<Object[]> data() throws Exception { + return Arrays.asList(new Object[][] { + {buildSimpleRemovePatch(), buildAddress(), buildExpectedRemovedAddress() }, + {buildComplexRemovePatch(), buildPerson(), buildExpectedPersonWithoutStreetAddress()}, + {buildArrayRemovePatchInPosition(), buildPerson(), buildPersonWithoutFirstPhone()} + }); + } + + private JsonObject pathOperation; + private JsonStructure target; + private JsonValue expectedResult; + + public JsonPointerRemoveOperationTest(JsonObject pathOperation, + JsonObject target, JsonValue expectedResult) { + super(); + this.pathOperation = pathOperation; + this.target = target; + this.expectedResult = expectedResult; + } + + @Test + public void shouldRemoveElementsToExistingJsonDocument() { + JsonPointer pointer = Json.createPointer(pathOperation.getString("path")); + JsonObject modified = (JsonObject) pointer.remove(target); + assertThat(modified, is(expectedResult)); + } + + static JsonObject buildPerson() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + static JsonObject buildAddress() { + return Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021") + .build(); + } + static JsonObject buildComplexRemovePatch() { + return Json.createObjectBuilder() + .add("op", "remove") + .add("path", "/address/streetAddress") + .build(); + } + static JsonObject buildSimpleRemovePatch() { + return Json.createObjectBuilder() + .add("op", "remove") + .add("path", "/streetAddress") + .build(); + } + static JsonObject buildArrayRemovePatchInPosition() { + return Json.createObjectBuilder() + .add("op", "remove") + .add("path", "/phoneNumber/0") + .build(); + } + static JsonObject buildExpectedRemovedAddress() { + return Json.createObjectBuilder() + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021") + .build(); + } + static JsonObject buildPersonWithoutFirstPhone() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + static JsonObject buildExpectedPersonWithoutStreetAddress() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPointerReplaceOperationTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPointerReplaceOperationTest.java new file mode 100644 index 0000000..a4661d9 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPointerReplaceOperationTest.java
@@ -0,0 +1,201 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.util.Arrays; + +import jakarta.json.Json; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * + * @author Alex Soto + * + */ +@RunWith(Parameterized.class) +public class JsonPointerReplaceOperationTest { + + @Parameters(name = "{index}: ({0})={1}") + public static Iterable<Object[]> data() throws Exception { + return Arrays.asList(new Object[][] { + {buildSimpleReplacePatch(), buildAddress(), buildExpectedAddress(), null}, + {buildComplexReplacePatch(), buildPerson(), buildExpectedPerson(), null}, + {buildArrayReplacePatchInPosition(), buildPerson(), buildExpectedPersonConcreteArrayPosition(), null}, + {buildArrayAddPatchInLastPosition(), buildPerson(), null, JsonException.class}, + {buildNoneExistingReplacePatch(), buildAddress(), null, JsonException.class} + }); + } + + private JsonObject pathOperation; + private JsonStructure target; + private JsonValue expectedResult; + private Class<? extends Exception> expectedException; + + public JsonPointerReplaceOperationTest(JsonObject pathOperation, + JsonStructure target, JsonValue expectedResult, Class<? extends Exception> expectedException) { + super(); + this.pathOperation = pathOperation; + this.target = target; + this.expectedResult = expectedResult; + this.expectedException = expectedException; + } + + @Test + public void shouldReplaceElementsToExistingJsonDocument() { + try { + JsonPointer pointer = Json.createPointer(pathOperation.getString("path")); + JsonObject modified = (JsonObject) pointer.replace(target, pathOperation.get("value")); + assertThat(modified, is(expectedResult)); + assertThat(expectedException, nullValue()); + } catch(Exception e) { + if(expectedException == null) { + fail(e.getMessage()); + } else { + assertThat(e, instanceOf(expectedException)); + } + } + } + + static JsonObject buildAddress() { + return Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021") + .build(); + } + static JsonObject buildComplexReplacePatch() { + return Json.createObjectBuilder() + .add("op", "add") + .add("path", "/address/streetAddress") + .add("value", "myaddress") + .build(); + } + static JsonObject buildSimpleReplacePatch() { + return Json.createObjectBuilder() + .add("op", "replace") + .add("path", "/streetAddress") + .add("value", "myaddress") + .build(); + } + static JsonObject buildNoneExistingReplacePatch() { + return Json.createObjectBuilder() + .add("op", "replace") + .add("path", "/notexists") + .add("value", "myaddress") + .build(); + } + static JsonObject buildArrayReplacePatchInPosition() { + return Json.createObjectBuilder() + .add("op", "replace") + .add("path", "/phoneNumber/0") + .add("value", Json.createObjectBuilder() + .add("type", "home") + .add("number", "200 555-1234")) + .build(); + } + static JsonObject buildArrayAddPatchInLastPosition() { + return Json.createObjectBuilder() + .add("op", "add") + .add("path", "/phoneNumber/-") + .add("value", Json.createObjectBuilder() + .add("type", "home") + .add("number", "200 555-1234")) + .build(); + } + static JsonObject buildExpectedAddress() { + return Json.createObjectBuilder() + .add("streetAddress", "myaddress") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021") + .build(); + } + static JsonObject buildPerson() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + static JsonObject buildExpectedPersonConcreteArrayPosition() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "21 2nd Street") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add((Json.createObjectBuilder() + .add("type", "home") + .add("number", "200 555-1234"))) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + static JsonObject buildExpectedPerson() { + return Json.createObjectBuilder() + .add("firstName", "John") + .add("lastName", "Smith") + .add("age", 25) + .add("address", Json.createObjectBuilder() + .add("streetAddress", "myaddress") + .add("city", "New York") + .add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", Json.createArrayBuilder() + .add(Json.createObjectBuilder() + .add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder() + .add("type", "fax") + .add("number", "646 555-4567"))) + .build(); + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPointerTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPointerTest.java new file mode 100644 index 0000000..6615e2f --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPointerTest.java
@@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.CoreMatchers.instanceOf; + +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.Arrays; + +import jakarta.json.Json; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; +import jakarta.json.JsonReader; +import jakarta.json.JsonValue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * + * @author Alex Soto + * + */ +@RunWith(Parameterized.class) +public class JsonPointerTest { + + private static JsonObject rfc6901Example; + + @Parameters(name = "{index}: ({0})={1}") + public static Iterable<Object[]> data() throws Exception { + rfc6901Example = JsonPointerTest.readRfc6901Example(); + return Arrays.asList(new Object[][] { + {Json.createPointer(""), rfc6901Example, null }, + {Json.createPointer("/foo"), rfc6901Example.getJsonArray("foo"), null}, + {Json.createPointer("/foo/0"), rfc6901Example.getJsonArray("foo").get(0), null}, + {Json.createPointer("/foo/5"), null, JsonException.class}, + {Json.createPointer("/p/1"), null, JsonException.class}, + {Json.createPointer("/"), rfc6901Example.getJsonNumber(""), null}, + {Json.createPointer("/a~1b"), rfc6901Example.getJsonNumber("a/b"), null}, + {Json.createPointer("/m~0n"), rfc6901Example.getJsonNumber("m~n"), null}, + {Json.createPointer("/c%d"), rfc6901Example.getJsonNumber("c%d"), null}, + {Json.createPointer("/e^f"), rfc6901Example.getJsonNumber("e^f"), null}, + {Json.createPointer("/g|h"), rfc6901Example.getJsonNumber("g|h"), null}, + {Json.createPointer("/i\\j"), rfc6901Example.getJsonNumber("i\\j"), null}, + {Json.createPointer("/k\"l"), rfc6901Example.getJsonNumber("k\"l"), null}, + {Json.createPointer("/ "), rfc6901Example.getJsonNumber(" "), null}, + {Json.createPointer("/notexists"), null, JsonException.class}, + {Json.createPointer("/s/t"), null, JsonException.class}, + {Json.createPointer("/o"), JsonObject.NULL, null} + }); + } + + private JsonPointer pointer; + private JsonValue expected; + private Class<? extends Exception> expectedException; + + public JsonPointerTest(JsonPointer pointer, JsonValue expected, Class<? extends Exception> expectedException) { + super(); + this.pointer = pointer; + this.expected = expected; + this.expectedException = expectedException; + } + + @Test + public void shouldEvaluateJsonPointerExpressions() { + try { + JsonValue result = pointer.getValue(rfc6901Example); + assertThat(result, is(expected)); + assertThat(expectedException, nullValue()); + } catch(Exception e) { + if(expectedException == null) { + fail(e.getMessage()); + } else { + assertThat(e, instanceOf(expectedException)); + } + } + } + + static JsonObject readRfc6901Example() throws Exception { + Reader rfc6901Reader = new InputStreamReader(JsonReaderTest.class.getResourceAsStream("/rfc6901.json")); + JsonReader reader = Json.createReader(rfc6901Reader); + JsonValue value = reader.readObject(); + reader.close(); + return (JsonObject) value; + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonPointerToStringTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonPointerToStringTest.java new file mode 100644 index 0000000..4da85b6 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonPointerToStringTest.java
@@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; + +import java.util.Arrays; + +import jakarta.json.Json; +import jakarta.json.JsonPointer; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * JSON pointer toString tests. + * + * @author leadpony + */ +@RunWith(Parameterized.class) +public class JsonPointerToStringTest { + + @Parameters(name = "{index}: {0}") + public static Iterable<Object> data() { + return Arrays.asList("", "/", "/one/two/3", "/a~1b", "/m~0n"); + } + + private final String expected; + + public JsonPointerToStringTest(String expected) { + this.expected = expected; + } + + @Test + public void shouldReturnOriginalEscapedString() { + JsonPointer pointer = Json.createPointer(expected); + assertThat(pointer.toString(), is(equalTo(expected))); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonReaderTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonReaderTest.java new file mode 100644 index 0000000..a7fca4d --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonReaderTest.java
@@ -0,0 +1,208 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonNumber; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonReaderFactory; +import jakarta.json.JsonValue; + +import org.glassfish.json.api.BufferPool; + +import junit.framework.TestCase; + +/** + * @author Jitendra Kotamraju + */ +public class JsonReaderTest extends TestCase { + public JsonReaderTest(String testName) { + super(testName); + } + + public void testObject() throws Exception { + JsonObject person = readPerson(); + JsonObjectTest.testPerson(person); + } + + public void testEscapedString() throws Exception { + // u00ff is escaped once, not escaped once + JsonReader reader = Json.createReader(new StringReader("[\"\\u0000\\u00ff\u00ff\"]")); + JsonArray array = reader.readArray(); + reader.close(); + String str = array.getString(0); + assertEquals("\u0000\u00ff\u00ff", str); + } + + public void testPrimitiveIntNumbers() { + String[] borderlineCases = new String[]{ + "214748364", + Integer.toString(Integer.MAX_VALUE), + Long.toString(Integer.MAX_VALUE + 1L), + "-214748364", + Integer.toString(Integer.MIN_VALUE), + Long.toString(Integer.MIN_VALUE - 1L) + }; + for (String num : borderlineCases) { + JsonReader reader = Json.createReader(new StringReader("["+num+"]")); + try { + JsonArray array = reader.readArray(); + JsonNumber value = (JsonNumber) array.get(0); + assertEquals("Fails for num="+num, new BigInteger(num).longValue(), value.longValue()); + } finally { + reader.close(); + } + } + } + + public void testPrimitiveLongNumbers() { + String[] borderlineCases = new String[]{ + "922337203685477580", + Long.toString(Long.MAX_VALUE), + new BigInteger(Long.toString(Long.MAX_VALUE)).add(BigInteger.ONE).toString(), + "-922337203685477580", + Long.toString(Long.MIN_VALUE), + new BigInteger(Long.toString(Long.MIN_VALUE)).subtract(BigInteger.ONE).toString() + }; + for (String num : borderlineCases) { + JsonReader reader = Json.createReader(new StringReader("["+num+"]")); + try { + JsonArray array = reader.readArray(); + JsonNumber value = (JsonNumber) array.get(0); + assertEquals("Fails for num="+num, new BigInteger(num), value.bigIntegerValueExact()); + } finally { + reader.close(); + } + } + } + + public void testUnknownFeature() throws Exception { + Map<String, Object> config = new HashMap<>(); + config.put("foo", true); + JsonReaderFactory factory = Json.createReaderFactory(config); + factory.createReader(new StringReader("{}")); + Map<String, ?> config1 = factory.getConfigInUse(); + if (config1.size() > 0) { + fail("Shouldn't have any config in use"); + } + } + + public void testIllegalStateExcepton() throws Exception { + JsonReader reader = Json.createReader(new StringReader("{}")); + reader.readObject(); + try { + reader.readObject(); + } catch (IllegalStateException expected) { + // no-op + } + reader.close(); + + reader = Json.createReader(new StringReader("[]")); + reader.readArray(); + try { + reader.readArray(); + } catch (IllegalStateException expected) { + // no-op + } + reader.close(); + + reader = Json.createReader(new StringReader("{}")); + reader.read(); + try { + reader.read(); + } catch (IllegalStateException expected) { + // no-op + } + reader.close(); + } + + static JsonObject readPerson() throws Exception { + Reader wikiReader = new InputStreamReader(JsonReaderTest.class.getResourceAsStream("/wiki.json")); + JsonReader reader = Json.createReader(wikiReader); + JsonValue value = reader.readObject(); + reader.close(); + return (JsonObject) value; + } + + // JSONP-23 cached empty string is not reset + public void testEmptyStringUsingStandardBuffer() throws Throwable { + JsonReaderFactory factory = Json.createReaderFactory(null); + StringBuilder sb = new StringBuilder(); + for(int i=0; i < 40000; i++) { + sb.append('a'); + String name = sb.toString(); + String str = "[1, \"\", \""+name+"\", \"\", \""+name+"\", \"\", 100]"; + try { + JsonReader reader = factory.createReader(new StringReader(str)); + JsonArray array = reader.readArray(); + assertEquals(1, array.getInt(0)); + assertEquals("", array.getString(1)); + assertEquals(name, array.getString(2)); + assertEquals("", array.getString(3)); + assertEquals(name, array.getString(4)); + assertEquals("", array.getString(5)); + assertEquals(100, array.getInt(6)); + reader.close(); + } catch (Throwable t) { + throw new Throwable("Failed for name length="+i, t); + } + } + } + + // JSONP-23 cached empty string is not reset + public void testEmptyStringUsingBuffers() throws Throwable { + for(int size=20; size < 500; size++) { + final JsonParserTest.MyBufferPool bufferPool = new JsonParserTest.MyBufferPool(size); + Map<String, Object> config = new HashMap<String, Object>() {{ + put(BufferPool.class.getName(), bufferPool); + }}; + JsonReaderFactory factory = Json.createReaderFactory(config); + + StringBuilder sb = new StringBuilder(); + for(int i=0; i < 1000; i++) { + sb.append('a'); + String name = sb.toString(); + String str = "[1, \"\", \""+name+"\", \"\", \""+name+"\", \"\", 100]"; + try { + JsonReader reader = factory.createReader(new StringReader(str)); + JsonArray array = reader.readArray(); + assertEquals(1, array.getInt(0)); + assertEquals("", array.getString(1)); + assertEquals(name, array.getString(2)); + assertEquals("", array.getString(3)); + assertEquals(name, array.getString(4)); + assertEquals("", array.getString(5)); + assertEquals(100, array.getInt(6)); + reader.close(); + } catch (Throwable t) { + throw new Throwable("Failed for buffer size="+size+" name length="+i, t); + } + } + } + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonSamplesParsingTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonSamplesParsingTest.java new file mode 100644 index 0000000..dd2702c --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonSamplesParsingTest.java
@@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.Json; +import jakarta.json.JsonException; +import jakarta.json.stream.JsonParser; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; + +/** + * JsonParser tests for sample files + * + * @author Jitendra Kotamraju + */ +public class JsonSamplesParsingTest extends TestCase { + + public void testSampleFiles() { + String[] fileNames = { + "facebook.json", "facebook1.json", "facebook2.json", + "twitter.json" + }; + for(String fileName: fileNames) { + try { + testSampleFile(fileName); + } catch(Exception e) { + throw new JsonException("Exception while parsing "+fileName, e); + } + } + } + + private void testSampleFile(String fileName) { + Reader reader = new InputStreamReader( + JsonSamplesParsingTest.class.getResourceAsStream("/"+fileName), StandardCharsets.UTF_8); + JsonParser parser = null; + try { + parser = Json.createParser(reader); + while(parser.hasNext()) { + parser.next(); + } + } finally { + if (parser != null) { + parser.close(); + } + } + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonStringTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonStringTest.java new file mode 100644 index 0000000..6f7e7a9 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonStringTest.java
@@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.*; +import java.io.StringReader; + +/** + * @author Jitendra Kotamraju + */ +public class JsonStringTest extends TestCase { + public JsonStringTest(String testName) { + super(testName); + } + + // tests JsonString#toString() + public void testToString() throws Exception { + escapedString(""); + escapedString("abc"); + escapedString("abc\f"); + escapedString("abc\na"); + escapedString("abc\tabc"); + escapedString("abc\n\tabc"); + escapedString("abc\n\tabc\r"); + escapedString("\n\tabc\r"); + escapedString("\bab\tb\rc\\\"\ftesting1234"); + escapedString("\f\babcdef\tb\rc\\\"\ftesting1234"); + escapedString("\u0000\u00ff"); + escapedString("abc\"\\/abc"); + } + + public void testHashCode() { + String string1 = new String("a"); + JsonString jsonString1 = Json.createValue(string1); + assertTrue(jsonString1.hashCode() == jsonString1.getString().hashCode()); + + String string2 = new String("a"); + JsonString jsonString2 = Json.createValue(string2); + + assertTrue(jsonString1.equals(jsonString2)); + assertTrue(jsonString1.hashCode() == jsonString2.hashCode()); + } + + void escapedString(String str) throws Exception { + JsonArray exp = Json.createArrayBuilder().add(str).build(); + String parseStr = "["+exp.get(0).toString()+"]"; + JsonReader jr = Json.createReader(new StringReader(parseStr)); + JsonArray got = jr.readArray(); + assertEquals(exp, got); + jr.close(); + } + +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonValueTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonValueTest.java new file mode 100644 index 0000000..af63746 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonValueTest.java
@@ -0,0 +1,171 @@ +/* + * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collections; +import jakarta.json.JsonObject; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author Lukas Jungmann + */ +public class JsonValueTest { + + @Test(expected = IndexOutOfBoundsException.class) + public void arrayGetJsonObjectIdx() { + JsonValue.EMPTY_JSON_ARRAY.getJsonObject(0); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void arrayGetJsonArrayIdx() { + JsonValue.EMPTY_JSON_ARRAY.getJsonArray(0); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void arrayGetJsonNumberIdx() { + JsonValue.EMPTY_JSON_ARRAY.getJsonNumber(0); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void arrayGetJsonStringIdx() { + JsonValue.EMPTY_JSON_ARRAY.getJsonString(0); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void arrayGetStringIdx() { + JsonValue.EMPTY_JSON_ARRAY.getString(0); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void arrayGetIntIdx() { + JsonValue.EMPTY_JSON_ARRAY.getInt(0); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void arrayGetBooleanIdx() { + JsonValue.EMPTY_JSON_ARRAY.getBoolean(0); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void arrayIsNull() { + JsonValue.EMPTY_JSON_ARRAY.isNull(0); + } + + @Test + public void arrayMethods() { + Assert.assertEquals(JsonValue.ValueType.ARRAY, JsonValue.EMPTY_JSON_ARRAY.getValueType()); + Assert.assertEquals(Collections.<JsonObject>emptyList(), JsonValue.EMPTY_JSON_ARRAY.getValuesAs(JsonObject.class)); + Assert.assertEquals(Collections.<String>emptyList(), JsonValue.EMPTY_JSON_ARRAY.getValuesAs(JsonString::getString)); + Assert.assertEquals(true, JsonValue.EMPTY_JSON_ARRAY.getBoolean(0, true)); + Assert.assertEquals(42, JsonValue.EMPTY_JSON_ARRAY.getInt(0, 42)); + Assert.assertEquals("Sasek", JsonValue.EMPTY_JSON_ARRAY.getString(0, "Sasek")); + } + + @Test(expected = UnsupportedOperationException.class) + public void arrayIsImmutable() { + JsonValue.EMPTY_JSON_ARRAY.add(JsonValue.EMPTY_JSON_OBJECT); + } + + @Test(expected = NullPointerException.class) + public void objectGetString() { + JsonValue.EMPTY_JSON_OBJECT.getString("normalni string"); + } + + @Test(expected = NullPointerException.class) + public void objectGetInt() { + JsonValue.EMPTY_JSON_OBJECT.getInt("hledej cislo"); + } + + @Test(expected = NullPointerException.class) + public void objectGetBoolean() { + JsonValue.EMPTY_JSON_OBJECT.getBoolean("booo"); + } + + @Test(expected = NullPointerException.class) + public void objectIsNull() { + JsonValue.EMPTY_JSON_OBJECT.isNull("???"); + } + + @Test + public void objectMethods() { + Assert.assertNull(JsonValue.EMPTY_JSON_OBJECT.getJsonArray("pole")); + Assert.assertNull(JsonValue.EMPTY_JSON_OBJECT.getJsonObject("objekt")); + Assert.assertNull(JsonValue.EMPTY_JSON_OBJECT.getJsonNumber("cislo")); + Assert.assertNull(JsonValue.EMPTY_JSON_OBJECT.getJsonString("divnej string")); + + Assert.assertEquals("ja jo", JsonValue.EMPTY_JSON_OBJECT.getString("nejsem tu", "ja jo")); + Assert.assertEquals(false, JsonValue.EMPTY_JSON_OBJECT.getBoolean("najdes mne", false)); + Assert.assertEquals(98, JsonValue.EMPTY_JSON_OBJECT.getInt("spatnej dotaz", 98)); + } + + + @Test(expected = UnsupportedOperationException.class) + public void objectImmutable() { + JsonValue.EMPTY_JSON_OBJECT.put("klauni", JsonValue.EMPTY_JSON_ARRAY); + } + + @Test + public void serialization() { + byte[] data = serialize(JsonValue.TRUE); + JsonValue value = deserialize(JsonValue.class, data); + Assert.assertEquals(JsonValue.TRUE, value); + + data = serialize(JsonValue.FALSE); + value = deserialize(JsonValue.class, data); + Assert.assertEquals(JsonValue.FALSE, value); + + data = serialize(JsonValue.NULL); + value = deserialize(JsonValue.class, data); + Assert.assertEquals(JsonValue.NULL, value); + + data = serialize(JsonValue.EMPTY_JSON_ARRAY); + value = deserialize(JsonValue.class, data); + Assert.assertEquals(JsonValue.EMPTY_JSON_ARRAY, value); + + data = serialize(JsonValue.EMPTY_JSON_OBJECT); + value = deserialize(JsonValue.class, data); + Assert.assertEquals(JsonValue.EMPTY_JSON_OBJECT, value); + } + + private byte[] serialize(Object o) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(o); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + return baos.toByteArray(); + } + + private <T> T deserialize(Class<T> type, byte[] data) { + ByteArrayInputStream bais = new ByteArrayInputStream(data); + try (ObjectInputStream ois = new ObjectInputStream(bais)) { + return (T) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/JsonWriterTest.java b/impl/src/test/java/org/glassfish/json/tests/JsonWriterTest.java new file mode 100644 index 0000000..c097d4e --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/JsonWriterTest.java
@@ -0,0 +1,229 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import jakarta.json.*; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringWriter; + +import junit.framework.TestCase; + +/** + * @author Jitendra Kotamraju + */ +public class JsonWriterTest extends TestCase { + public JsonWriterTest(String testName) { + super(testName); + } + + public void testObject() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.writeObject(Json.createObjectBuilder().build()); + jsonWriter.close(); + writer.close(); + + assertEquals("{}", writer.toString()); + } + + public void testEmptyObject() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.write(JsonValue.EMPTY_JSON_OBJECT); + jsonWriter.close(); + writer.close(); + + assertEquals("{}", writer.toString()); + } + + public void testArray() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.writeArray(Json.createArrayBuilder().build()); + jsonWriter.close(); + writer.close(); + + assertEquals("[]", writer.toString()); + } + + public void testEmptyArray() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.write(JsonValue.EMPTY_JSON_ARRAY); + jsonWriter.close(); + writer.close(); + + assertEquals("[]", writer.toString()); + } + + public void testNumber() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.writeArray(Json.createArrayBuilder().add(10).build()); + jsonWriter.close(); + writer.close(); + + assertEquals("[10]", writer.toString()); + } + + public void testDoubleNumber() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.writeArray(Json.createArrayBuilder().add(10.5).build()); + jsonWriter.close(); + writer.close(); + + assertEquals("[10.5]", writer.toString()); + } + + public void testArrayString() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.writeArray(Json.createArrayBuilder().add("string").build()); + jsonWriter.close(); + writer.close(); + + assertEquals("[\"string\"]", writer.toString()); + } + + public void testObjectAsValue() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.write((JsonValue) (Json.createObjectBuilder().build())); + jsonWriter.close(); + writer.close(); + + assertEquals("{}", writer.toString()); + } + + public void testNullValue() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.write(JsonValue.NULL); + jsonWriter.close(); + writer.close(); + + assertEquals("null", writer.toString()); + } + + public void testTrueValue() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.write(JsonValue.TRUE); + jsonWriter.close(); + writer.close(); + + assertEquals("true", writer.toString()); + } + + public void testFalseValue() throws Exception { + StringWriter writer = new StringWriter(); + JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.write(JsonValue.FALSE); + jsonWriter.close(); + writer.close(); + + assertEquals("false", writer.toString()); + } + + public void testIllegalStateExcepton() throws Exception { + JsonObject obj = Json.createObjectBuilder().build(); + JsonArray array = Json.createArrayBuilder().build(); + + JsonWriter writer = Json.createWriter(new StringWriter()); + writer.writeObject(obj); + try { + writer.writeObject(obj); + } catch (IllegalStateException expected) { + // no-op + } + writer.close(); + + writer = Json.createWriter(new StringWriter()); + writer.writeArray(array); + try { + writer.writeArray(array); + } catch (IllegalStateException expected) { + // no-op + } + writer.close(); + + writer = Json.createWriter(new StringWriter()); + writer.write(array); + try { + writer.writeArray(array); + } catch (IllegalStateException expected) { + // no-op + } + writer.close(); + } + + public void testNoCloseWriteObjectToStream() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriter(baos); + writer.write(Json.createObjectBuilder().build()); + // not calling writer.close() intentionally + assertEquals("{}", baos.toString("UTF-8")); + } + + public void testNoCloseWriteObjectToWriter() throws Exception { + StringWriter sw = new StringWriter(); + JsonWriter writer = Json.createWriter(sw); + writer.write(Json.createObjectBuilder().build()); + // not calling writer.close() intentionally + assertEquals("{}", sw.toString()); + } + + public void testNoCloseWriteArrayToStream() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriter(baos); + writer.write(Json.createArrayBuilder().build()); + // not calling writer.close() intentionally + assertEquals("[]", baos.toString("UTF-8")); + } + + public void testNoCloseWriteArrayToWriter() throws Exception { + StringWriter sw = new StringWriter(); + JsonWriter writer = Json.createWriter(sw); + writer.write(Json.createArrayBuilder().build()); + // not calling writer.close() intentionally + assertEquals("[]", sw.toString()); + } + + public void testClose() throws Exception { + MyByteStream baos = new MyByteStream(); + JsonWriter writer = Json.createWriter(baos); + writer.write(Json.createObjectBuilder().build()); + writer.close(); + assertEquals("{}", baos.toString("UTF-8")); + assertTrue(baos.isClosed()); + } + + private static final class MyByteStream extends ByteArrayOutputStream { + boolean closed; + + boolean isClosed() { + return closed; + } + + public void close() throws IOException { + super.close(); + closed = true; + } + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/RFC7159Test.java b/impl/src/test/java/org/glassfish/json/tests/RFC7159Test.java new file mode 100644 index 0000000..b4b7da8 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/RFC7159Test.java
@@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import org.junit.Test; +import org.junit.BeforeClass; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import jakarta.json.*; +import jakarta.json.stream.JsonGenerator; +import java.io.StringWriter; +import java.io.StringReader; + +/** + * @author Kin-man Chung + */ +public class RFC7159Test { + + @Test + public void testCreatValues() { + JsonArrayBuilder builder = Json.createArrayBuilder(); + JsonArray array = builder.add(Json.createValue("someString")) + .add(Json.createValue(100)) + .add(Json.createValue(12345.6789)) + .build(); + builder = Json.createArrayBuilder(); + JsonArray expected = builder.add("someString") + .add(100) + .add(12345.6789) + .build(); + assertEquals(expected, array); + } + + @Test + public void testReadValues() { + JsonReader reader = Json.createReader(new StringReader("\"someString\"")); + JsonArrayBuilder builder = Json.createArrayBuilder(); + builder.add(reader.readValue()); + reader = Json.createReader(new StringReader("100")); + builder.add(reader.readValue()); + reader = Json.createReader(new StringReader("12345.6789")); + builder.add(reader.readValue()); + JsonArray array = builder.build(); + builder = Json.createArrayBuilder(); + JsonArray expected = builder.add("someString") + .add(100) + .add(12345.6789) + .build(); + assertEquals(expected, array); + } + + @Test + public void testWriteValues() { + StringWriter stringWriter = new StringWriter(); + JsonWriter writer = Json.createWriter(stringWriter); + writer.write(Json.createValue("someString")); + assertEquals("\"someString\"", stringWriter.toString()); + + stringWriter = new StringWriter(); + writer = Json.createWriter(stringWriter); + writer.write(Json.createValue(100)); + assertEquals("100", stringWriter.toString()); + + stringWriter = new StringWriter(); + writer = Json.createWriter(stringWriter); + writer.write(Json.createValue(12345.6789)); + assertEquals("12345.6789", stringWriter.toString()); + } + + @Test + public void testGeneratorValues() { + StringWriter stringWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(stringWriter); + generator.write("someString").close(); + assertEquals("\"someString\"", stringWriter.toString()); + + stringWriter = new StringWriter(); + generator = Json.createGenerator(stringWriter); + generator.write(100).close(); + assertEquals("100", stringWriter.toString()); + + stringWriter = new StringWriter(); + generator = Json.createGenerator(stringWriter); + generator.write(12345.6789).close(); + assertEquals("12345.6789", stringWriter.toString()); + } +}
diff --git a/impl/src/test/java/org/glassfish/json/tests/ToJsonTest.java b/impl/src/test/java/org/glassfish/json/tests/ToJsonTest.java new file mode 100644 index 0000000..94893a2 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/ToJsonTest.java
@@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import org.junit.Test; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonValue; + +import org.glassfish.json.JsonUtil; + +import static org.junit.Assert.assertEquals; +/** + * @author Kin-man Chung + */ +public class ToJsonTest { + + @Test + public void testToJson() { + assertEquals(Json.createValue("someString"), JsonUtil.toJson("'someString'")); + assertEquals(Json.createValue("some'thing"), JsonUtil.toJson("'some\\'thing'")); + assertEquals(Json.createValue("some\"thing"), JsonUtil.toJson("'some\\\"thing'")); + JsonArrayBuilder builder = Json.createArrayBuilder(); + JsonArray array = builder + .add(Json.createObjectBuilder() + .add("name", "John") + .add("age", 35) + .add("educations", Json.createArrayBuilder() + .add("Gunn High") + .add("UC Berkeley"))) + .add(Json.createObjectBuilder() + .add("name", "Jane") + .add("educations", Json.createArrayBuilder() + .add("Oxford"))) + .build(); + JsonValue expected = JsonUtil.toJson( + "[ { 'name': 'John', " + + "'age': 35, " + + "'educations': ['Gunn High', 'UC Berkeley'] }, " + + " { 'name': 'Jane', " + + "'educations': ['Oxford']}]"); + assertEquals(expected, array); + } +} +
diff --git a/impl/src/test/java/org/glassfish/json/tests/TwitterSearchTest.java b/impl/src/test/java/org/glassfish/json/tests/TwitterSearchTest.java new file mode 100644 index 0000000..342d626 --- /dev/null +++ b/impl/src/test/java/org/glassfish/json/tests/TwitterSearchTest.java
@@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.tests; + +import junit.framework.TestCase; + +import jakarta.json.*; +import jakarta.json.stream.JsonParser; +import jakarta.json.stream.JsonParser.Event; +import java.io.*; +import java.net.URL; + +/** + * JsonParser Tests using twitter search API + * + * @author Jitendra Kotamraju + */ +public class TwitterSearchTest extends TestCase { + + public void test() { + // dummy test so that junit doesn't complain + } + + public void xtestStreamTwitter() throws Exception { + URL url = new URL("http://search.twitter.com/search.json?q=%23java&rpp=100"); + InputStream is = url.openStream(); + JsonParser parser = Json.createParser(is); + + while(parser.hasNext()) { + Event e = parser.next(); + if (e == Event.KEY_NAME) { + if (parser.getString().equals("from_user")) { + parser.next(); + System.out.print(parser.getString()); + System.out.print(": "); + } else if (parser.getString().equals("text")) { + parser.next(); + System.out.println(parser.getString()); + System.out.println("---------"); + } + } + } + parser.close(); + } + + public void xtestObjectTwitter() throws Exception { + URL url = new URL("http://search.twitter.com/search.json?q=%23java&rpp=100"); + InputStream is = url.openStream(); + JsonReader rdr = Json.createReader(is); + JsonObject obj = rdr.readObject(); + JsonArray results = obj.getJsonArray("results"); + for(JsonObject result : results.getValuesAs(JsonObject.class)) { + System.out.print(result.get("from_user")); + System.out.print(": "); + System.out.println(result.get("text")); + System.out.println("-----------"); + } + rdr.close(); + } + +}
diff --git a/impl/src/test/resources/facebook.json b/impl/src/test/resources/facebook.json new file mode 100644 index 0000000..1a82909 --- /dev/null +++ b/impl/src/test/resources/facebook.json
@@ -0,0 +1,668 @@ +{ + "data": [ + { + "id": "123_1", + "from": { + "name": "Name 1", + "id": "1" + }, + "message": "Dummy message Name 1", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for iPhone", + "namespace": "fbiphone", + "id": "12345" + }, + "created_time": "2013-07-26T22:33:09+0000", + "updated_time": "2013-07-26T22:33:09+0000" + }, + { + "id": "123_2", + "from": { + "category": "Author", + "name": "Name 2", + "id": "2" + }, + "message": "Dummy message Name 2", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/9879asd/987645" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "23456" + }, + "created_time": "2013-07-26T22:33:03+0000", + "updated_time": "2013-07-26T22:33:03+0000" + }, + { + "id": "123_3", + "from": { + "category": "Community", + "name": "Group 1", + "id": "3" + }, + "message": "Dummy message Group 1", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/68548" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "23456" + }, + "created_time": "2013-07-26T22:33:00+0000", + "updated_time": "2013-07-26T22:33:00+0000" + }, + { + "id": "123_4", + "from": { + "category": "Bank/financial institution", + "name": "Group 2", + "id": "4" + }, + "message": "Dummy message Group 2", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/1234" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Seesmic", + "id": "34567" + }, + "created_time": "2013-07-26T22:32:58+0000", + "updated_time": "2013-07-26T22:32:58+0000" + }, + { + "id": "123_5", + "from": { + "name": "Person 5", + "id": "5" + }, + "message": "Dummy message Person 5", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:32:55+0000", + "updated_time": "2013-07-26T22:32:55+0000" + }, + { + "id": "123_6", + "from": { + "name": "Person 6", + "id": "6" + }, + "message": "Dummy message Person 6", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "23456" + }, + "created_time": "2013-07-26T22:32:46+0000", + "updated_time": "2013-07-26T22:32:46+0000" + }, + { + "id": "123_7", + "from": { + "category": "Community", + "name": "\u0e2a\u0e19Group 7", + "id": "7" + }, + "message": "Dummy message Group 7", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/7" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "DoubleQ", + "namespace": "doubleqapp", + "id": "98765" + }, + "created_time": "2013-07-26T22:32:41+0000", + "updated_time": "2013-07-26T22:32:41+0000" + }, + { + "id": "123_8", + "from": { + "name": "Person 8", + "id": "8" + }, + "message": "Dummy message Person 8", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "23456" + }, + "created_time": "2013-07-26T22:32:36+0000", + "updated_time": "2013-07-26T22:32:36+0000" + }, + { + "id": "123_9", + "from": { + "category": "Bank/financial institution", + "name": "Group 9", + "id": "9" + }, + "message": "Dummy message Group 9", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/9" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Status Shuffle", + "namespace": "status-shuffle", + "id": "87654" + }, + "created_time": "2013-07-26T22:32:30+0000", + "updated_time": "2013-07-26T22:32:30+0000" + }, + { + "id": "123_10", + "from": { + "name": "Person 10", + "id": "10" + }, + "message": "Dummy message Person 10", + "picture": "https://picture.url/123/10.jpg", + "link": "https://custom.url/123/10", + "name": "Dummy page name - Person 10", + "caption": "www.page.com", + "description": "Some random description", + "icon": "https://icon.url/123/10.ico", + "privacy": { + "value": "" + }, + "type": "link", + "created_time": "2013-07-26T22:32:14+0000", + "updated_time": "2013-07-26T22:32:14+0000" + }, + { + "id": "123_11", + "from": { + "category": "Community", + "name": "Group 11", + "id": "11" + }, + "message": "Dummy message Group 11", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/11" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "twitterfeed", + "id": "654987" + }, + "created_time": "2013-07-26T22:32:13+0000", + "updated_time": "2013-07-26T22:32:13+0000" + }, + { + "id": "123_12", + "from": { + "category": "Entertainer", + "name": "Person 12", + "id": "12" + }, + "message": "Dummy message Person 12", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/12" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "23456" + }, + "created_time": "2013-07-26T22:32:10+0000", + "updated_time": "2013-07-26T22:32:10+0000" + }, + { + "id": "123_13", + "from": { + "category": "Health/beauty", + "name": "Group 13", + "id": "13" + }, + "message": "Dummy message Group 13", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/13" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "twitterfeed", + "id": "654987" + }, + "created_time": "2013-07-26T22:32:07+0000", + "updated_time": "2013-07-26T22:32:07+0000" + }, + { + "id": "123_14", + "from": { + "name": "Person 14", + "id": "14" + }, + "message": "Dummy message Person 14", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "23456" + }, + "created_time": "2013-07-26T22:31:53+0000", + "updated_time": "2013-07-26T22:31:53+0000" + }, + { + "id": "123_15", + "from": { + "category": "Community", + "name": "Group 15", + "id": "15" + }, + "message": "Dummy message Group 15", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/15" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "23456" + }, + "created_time": "2013-07-26T22:31:40+0000", + "updated_time": "2013-07-26T22:31:40+0000" + }, + { + "id": "123_16", + "from": { + "name": "Person 16", + "id": "16" + }, + "message": "Dummy message Person 16", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Nokia", + "id": "34567" + }, + "created_time": "2013-07-26T22:31:39+0000", + "updated_time": "2013-07-26T22:31:39+0000" + }, + { + "id": "123_17", + "from": { + "name": "Person 17", + "id": "17" + }, + "to": { + "data": [ + { + "name": "Person 16", + "id": "16" + } + ] + }, + "with_tags": { + "data": [ + { + "name": "Person 16", + "id": "16" + } + ] + }, + "message": "Dummy message Person 16", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for iPhone", + "namespace": "fbiphone", + "id": "123456" + }, + "created_time": "2013-07-26T22:31:38+0000", + "updated_time": "2013-07-26T22:31:38+0000" + }, + { + "id": "123_18", + "from": { + "category": "Bank/financial institution", + "name": "Group 18", + "id": "18" + }, + "message": "Dummy message Group 18", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/18" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Status Shuffle", + "namespace": "status-shuffle", + "id": "876543" + }, + "created_time": "2013-07-26T22:31:37+0000", + "updated_time": "2013-07-26T22:31:37+0000" + }, + { + "id": "123_19", + "from": { + "category": "Community", + "name": "Group 19", + "id": "19" + }, + "message": "Dummy message Group 19", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/19" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "23456" + }, + "created_time": "2013-07-26T22:31:36+0000", + "updated_time": "2013-07-26T22:31:36+0000" + }, + { + "id": "123_20", + "from": { + "name": "Person 20", + "id": "20" + }, + "message": "Dummy message Person 20", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:31:36+0000", + "updated_time": "2013-07-26T22:31:36+0000" + }, + { + "id": "123_21", + "from": { + "category": "Website", + "name": "Page 21", + "id": "21" + }, + "message": "Dummy message Page 21", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/21" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "dlvr.it", + "namespace": "dlvr_it", + "id": "456321" + }, + "created_time": "2013-07-26T22:31:34+0000", + "updated_time": "2013-07-26T22:31:34+0000" + }, + { + "id": "123_22", + "from": { + "name": "Person 22", + "id": "22" + }, + "to": { + "data": [ + { + "name": "Person 99", + "id": "99" + }, + { + "name": "Person 98", + "id": "98" + }, + { + "name": "Person 97", + "id": "97" + }, + { + "name": "Person 96", + "id": "96" + }, + { + "name": "Person 95", + "id": "95" + }, + { + "name": "Person 94", + "id": "94" + }, + { + "name": "Person 93", + "id": "93" + }, + { + "name": "Person 92", + "id": "92" + } + ] + }, + "message": "Dummy message Person 22", + "message_tags": { + "50": [ + { + "id": "99", + "name": "Person 99", + "type": "user", + "offset": 50, + "length": 13 + } + ], + "64": [ + { + "id": "98", + "name": "Person 98", + "type": "user", + "offset": 64, + "length": 25 + } + ], + "90": [ + { + "id": "97", + "name": "Person 97", + "type": "user", + "offset": 90, + "length": 11 + } + ], + "102": [ + { + "id": "96", + "name": "Person 96", + "type": "user", + "offset": 102, + "length": 14 + } + ], + "117": [ + { + "id": "95", + "name": "Person 95", + "type": "user", + "offset": 117, + "length": 17 + } + ], + "135": [ + { + "id": "94", + "name": "Person 94", + "type": "user", + "offset": 135, + "length": 13 + } + ], + "149": [ + { + "id": "93", + "name": "Person 93", + "type": "user", + "offset": 149, + "length": 21 + } + ], + "171": [ + { + "id": "92", + "name": "Person 92", + "type": "user", + "offset": 171, + "length": 11 + } + ] + }, + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:31:33+0000", + "updated_time": "2013-07-26T22:31:33+0000" + }, + { + "id": "123_23", + "from": { + "name": "Person 23", + "id": "23" + }, + "message": "Dummy message Person 23", + "picture": "https://custom.url/123/23.jpg", + "link": "https://custom.url/123/23", + "name": "Person 23 Name", + "caption": " ", + "description": " ", + "icon": "https://custom.url/123/23.gif", + "privacy": { + "value": "" + }, + "type": "link", + "application": { + "name": "RSS Graffiti", + "namespace": "rssgraffiti", + "id": "357951" + }, + "created_time": "2013-07-26T22:31:29+0000", + "updated_time": "2013-07-26T22:31:29+0000" + }, + { + "id": "123_24", + "from": { + "name": "Person 24", + "id": "24" + }, + "message": "Dummy message person 24", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for Android", + "namespace": "fbandroid", + "id": "123456" + }, + "created_time": "2013-07-26T22:31:29+0000", + "updated_time": "2013-07-26T22:31:29+0000" + }, + { + "id": "123_25", + "from": { + "name": "Person 25", + "id": "25" + }, + "message": "Dummy message Person 25", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:31:22+0000", + "updated_time": "2013-07-26T22:31:22+0000" + } + ], + "paging": { + "previous": "https://custom.url/previous", + "next": "https://custom.url/next" + } +} \ No newline at end of file
diff --git a/impl/src/test/resources/facebook1.json b/impl/src/test/resources/facebook1.json new file mode 100644 index 0000000..5016652 --- /dev/null +++ b/impl/src/test/resources/facebook1.json
@@ -0,0 +1,911 @@ +{ + "data": [ + { + "id": "123_1", + "from": { + "category": "Bank/financial institution", + "name": "Group 1", + "id": "1" + }, + "message": "Dummy message Group 1", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/1" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Seesmic", + "id": "23456" + }, + "created_time": "2013-07-26T22:45:54+0000", + "updated_time": "2013-07-26T22:45:54+0000" + }, + { + "id": "123_2", + "from": { + "name": "Person 2", + "id": "2" + }, + "message": "Dummy message Person 2", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:45:52+0000", + "updated_time": "2013-07-26T22:45:52+0000" + }, + { + "id": "123_3", + "from": { + "category": "Outdoor gear/sporting goods", + "category_list": [ + { + "id": "2231", + "name": "Outdoor Gear/Sporting Goods" + } + ], + "name": "Store 3", + "id": "3" + }, + "message": "https://shop.url/123/3", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/3" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:45:51+0000", + "updated_time": "2013-07-26T22:45:51+0000" + }, + { + "id": "123_4", + "from": { + "name": "Person 4", + "id": "4" + }, + "message": "Dummy message Person 4", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "123456" + }, + "created_time": "2013-07-26T22:45:50+0000", + "updated_time": "2013-07-26T22:45:50+0000" + }, + { + "id": "123_5", + "from": { + "name": "Person 5", + "id": "5" + }, + "to": { + "data": [ + { + "name": "Person 2", + "id": "2" + }, + { + "name": "Person 99", + "id": "99" + }, + { + "name": "Person 98", + "id": "98" + } + ] + }, + "message": "Dummy message Person 5", + "message_tags": { + "38": [ + { + "id": "2", + "name": "Person 2", + "type": "user", + "offset": 38, + "length": 13 + } + ], + "53": [ + { + "id": "99", + "name": "Person 99", + "type": "user", + "offset": 53, + "length": 17 + } + ], + "73": [ + { + "id": "98", + "name": "Person 98", + "type": "user", + "offset": 73, + "length": 18 + } + ] + }, + "story": "Dummy story Person 5", + "story_tags": { + "0": [ + { + "id": "97", + "name": "Person 97", + "offset": 0, + "length": 15, + "type": "user" + } + ], + "23": [ + { + "id": "96", + "name": "Person 96", + "offset": 23, + "length": 18, + "type": "user" + } + ] + }, + "picture": "https://custom.url/123/5.jpg", + "link": "https://profile.url/123/5", + "name": "Person 5 Photos", + "properties": [ + { + "name": "By", + "text": "Person 5", + "href": "https://profile.url/123/5" + } + ], + "icon": "https://custom.url/123/5.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "123", + "application": { + "name": "Photos", + "id": "1234" + }, + "created_time": "2013-07-26T22:45:45+0000", + "updated_time": "2013-07-26T22:45:45+0000" + }, + { + "id": "123_6", + "from": { + "category": "Public figure", + "name": "Person 6", + "id": "6" + }, + "message": "Dummy message Person 6", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/6" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:45:44+0000", + "updated_time": "2013-07-26T22:45:44+0000" + }, + { + "id": "123_7", + "from": { + "name": "Person 7", + "id": "7" + }, + "to": { + "data": [ + { + "name": "Person 89", + "id": "89" + } + ] + }, + "message": "Dummy message Person 7", + "message_tags": { + "16": [ + { + "id": "987", + "name": "Person 987", + "type": "user", + "offset": 16, + "length": 18 + } + ] + }, + "picture": "https://custom.url/123/7.jpg", + "link": "https://custom.url/123/7", + "source": "https://source.url/123/7", + "name": "Link name person 7", + "description": "Description Person 7", + "icon": "https://custom.url/123/7.gif", + "privacy": { + "value": "" + }, + "type": "video", + "created_time": "2013-07-26T22:45:44+0000", + "updated_time": "2013-07-26T22:45:44+0000" + }, + { + "id": "123_8", + "from": { + "name": "Person 8", + "id": "8" + }, + "to": { + "data": [ + { + "name": "Person 1", + "id": "1" + }, + { + "name": "Person 2", + "id": "2" + }, + { + "name": "Person 3", + "id": "3" + }, + { + "name": "Person 4", + "id": "4" + }, + { + "name": "Person 5", + "id": "5" + }, + { + "name": "Person 99", + "id": "99" + }, + { + "name": "Person 98", + "id": "98" + }, + { + "name": "Person 69", + "id": "69" + } + ] + }, + "message": "Dummy message Person 8", + "message_tags": { + "77": [ + { + "id": "1", + "name": "Person 1", + "type": "user", + "offset": 77, + "length": 26 + } + ], + "104": [ + { + "id": "2", + "name": "Person 2", + "type": "user", + "offset": 104, + "length": 11 + } + ], + "116": [ + { + "id": "3", + "name": "Person 3", + "type": "user", + "offset": 116, + "length": 13 + } + ], + "130": [ + { + "id": "4", + "name": "Person 4", + "type": "user", + "offset": 130, + "length": 22 + } + ], + "153": [ + { + "id": "5", + "name": "Person 5", + "type": "user", + "offset": 153, + "length": 20 + } + ], + "174": [ + { + "id": "99", + "name": "Person 99", + "type": "user", + "offset": 174, + "length": 12 + } + ], + "187": [ + { + "id": "98", + "name": "Person 98", + "type": "user", + "offset": 187, + "length": 16 + } + ], + "204": [ + { + "id": "69", + "name": "Person 69", + "type": "user", + "offset": 204, + "length": 21 + } + ] + }, + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:45:41+0000", + "updated_time": "2013-07-26T22:45:41+0000" + }, + { + "id": "123_9", + "from": { + "name": "Person 9", + "id": "9" + }, + "message": "Dummy message Person 9", + "story": "Story Person 9", + "story_tags": { + "0": [ + { + "id": "8", + "name": "Person 8", + "offset": 0, + "length": 10, + "type": "user" + } + ] + }, + "picture": "https://custom.url/123/9.jpg", + "link": "https://custom.url/123/9", + "icon": "https://custom.url/123/9.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_8", + "application": { + "name": "Facebook for Android", + "namespace": "fbandroid", + "id": "34567" + }, + "created_time": "2013-07-26T22:45:33+0000", + "updated_time": "2013-07-26T22:45:33+0000" + }, + { + "id": "123_9", + "from": { + "name": "Person 9", + "id": "9" + }, + "message": "Dummy message Person 9", + "story": "Story Person 9", + "story_tags": { + "0": [ + { + "id": "6", + "name": "Person 6", + "offset": 0, + "length": 13, + "type": "user" + } + ], + "21": [ + { + "id": "7", + "name": "Person 7", + "offset": 21, + "length": 25, + "type": "user" + } + ] + }, + "picture": "https://custom.url/123/9.jpg", + "link": "https://custom.url/123/9", + "name": "Link Person 9", + "caption": "Caption Person 9", + "properties": [ + { + "name": "By", + "text": "Person 9", + "href": "https://custom.url/123/9" + } + ], + "icon": "https://custom.url/123/9.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_9", + "application": { + "name": "Links", + "id": "951753" + }, + "created_time": "2013-07-26T22:45:33+0000", + "updated_time": "2013-07-26T22:45:33+0000" + }, + { + "id": "123_10", + "from": { + "name": "Person 10", + "id": "10" + }, + "message": "Dummy message Person 10", + "story": "Story Person 10", + "story_tags": { + "0": [ + { + "id": "3", + "name": "Person 3", + "offset": 0, + "length": 27, + "type": "user" + } + ], + "35": [ + { + "id": "79", + "name": "Page 79", + "offset": 35, + "length": 4, + "type": "page" + } + ] + }, + "picture": "https://custom.url/123/10.jpg", + "link": "https://link.url/123/10", + "name": "Timeline Photos", + "caption": "Caption link Person 10", + "properties": [ + { + "name": "By", + "text": "Page 79", + "href": "https://custom.url/123/79" + } + ], + "icon": "https://custom.url/123/10.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_10", + "application": { + "name": "Photos", + "id": "3456" + }, + "created_time": "2013-07-26T22:45:31+0000", + "updated_time": "2013-07-26T22:45:31+0000" + }, + { + "id": "123_11", + "from": { + "name": "Person 11", + "id": "11" + }, + "message": "Dummy message Person 11", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for iPhone", + "namespace": "fbiphone", + "id": "23456" + }, + "created_time": "2013-07-26T22:45:25+0000", + "updated_time": "2013-07-26T22:45:25+0000" + }, + { + "id": "123_12", + "from": { + "name": "Person 12", + "id": "12" + }, + "message": "Dummy message Person 12", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "3456" + }, + "created_time": "2013-07-26T22:45:20+0000", + "updated_time": "2013-07-26T22:45:20+0000" + }, + { + "id": "123_13", + "from": { + "name": "Person 13", + "id": "13" + }, + "message": "Dummy message person 13", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:45:18+0000", + "updated_time": "2013-07-26T22:45:18+0000" + }, + { + "id": "123_14", + "from": { + "name": "Person 14", + "id": "14" + }, + "message": "Dummy message Person 14", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:45:17+0000", + "updated_time": "2013-07-26T22:45:17+0000" + }, + { + "id": "123_15", + "from": { + "name": "Person 15", + "id": "15" + }, + "message": "Dummy message Person 15", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:45:16+0000", + "updated_time": "2013-07-26T22:45:16+0000" + }, + { + "id": "123_16", + "from": { + "name": "Person 16", + "id": "16" + }, + "message": "Dummy message Person 16", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "3456" + }, + "created_time": "2013-07-26T22:45:15+0000", + "updated_time": "2013-07-26T22:45:15+0000" + }, + { + "id": "123_17", + "from": { + "name": "Person 17", + "id": "17" + }, + "message": "Dummy message Person 17", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:45:12+0000", + "updated_time": "2013-07-26T22:45:12+0000" + }, + { + "id": "123_18", + "from": { + "name": "Person 18", + "id": "18" + }, + "message": "Dummy message Person 18", + "picture": "https://custom.url/123/18.jpg", + "link": "https://link.url/123/18", + "icon": "https://custom.url/123/18.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_18", + "created_time": "2013-07-26T22:45:11+0000", + "updated_time": "2013-07-26T22:45:11+0000" + }, + { + "id": "123_19", + "from": { + "name": "Person 19", + "id": "19" + }, + "message": "Dummy message Person 19", + "story": "Person 19 Story", + "story_tags": { + "0": [ + { + "id": "19", + "name": "Person 19", + "offset": 0, + "length": 13, + "type": "user" + } + ], + "21": [ + { + "id": "75", + "name": "Person 75", + "offset": 21, + "length": 31, + "type": "page" + } + ] + }, + "picture": "https://custom.url/123/19.jpg", + "link": "https://link.url/123/19", + "name": "Person 19 Photos", + "caption": "Caption Person 19", + "properties": [ + { + "name": "By", + "text": "Group 89", + "href": "https://custom.url/123/19" + } + ], + "icon": "https://custom.url/123/19.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_19", + "application": { + "name": "Photos", + "id": "12375" + }, + "created_time": "2013-07-26T22:45:07+0000", + "updated_time": "2013-07-26T22:45:07+0000" + }, + { + "id": "123_20", + "from": { + "name": "Person 20", + "id": "20" + }, + "message": "Dummy message Person 20", + "story": "Person 20 shared a photo.", + "story_tags": { + "0": [ + { + "id": "20", + "name": "Person 20", + "offset": 0, + "length": 21, + "type": "user" + } + ] + }, + "picture": "https://custom.url/123/20.jpg", + "link": "https://link.url/123/23", + "name": "Person 20's Photos", + "properties": [ + { + "name": "By", + "text": "Person 20", + "href": "https://custom.url/123/20" + } + ], + "icon": "https://custom.url/123/20.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_20", + "application": { + "name": "Photos", + "id": "45678" + }, + "created_time": "2013-07-26T22:45:00+0000", + "updated_time": "2013-07-26T22:45:00+0000" + }, + { + "id": "123_21", + "from": { + "name": "Person 21", + "id": "21" + }, + "message": "Dummy message Person 21", + "story": "Person 21 shared something.", + "story_tags": { + "0": [ + { + "id": "21", + "name": "Person 21", + "offset": 0, + "length": 18, + "type": "user" + } + ], + "26": [ + { + "id": "67", + "name": "Group 67", + "offset": 26, + "length": 30, + "type": "page" + } + ] + }, + "picture": "https://custom.url/123/21.jpg", + "link": "https://link.url/123/21", + "name": "Timeline Photos", + "caption": "Person 21 Caption", + "properties": [ + { + "name": "By", + "text": "Group 75", + "href": "https://custom.url/123/75" + } + ], + "icon": "https://custom.url/123/21.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_21", + "application": { + "name": "Photos", + "id": "123456" + }, + "created_time": "2013-07-26T22:44:58+0000", + "updated_time": "2013-07-26T22:44:58+0000" + }, + { + "id": "123_22", + "from": { + "name": "Person 22", + "id": "22" + }, + "message": "Dummy message Person 22", + "story": "Person 22 shared photo.", + "story_tags": { + "0": [ + { + "id": "22", + "name": "Person 22", + "offset": 0, + "length": 21, + "type": "user" + } + ], + "29": [ + { + "id": "88", + "name": "Person 88", + "offset": 29, + "length": 12, + "type": "page" + } + ] + }, + "picture": "https://custom.url/123/22.jpg", + "link": "https://link.url/123/22", + "name": "Timeline Photos", + "caption": "Person 22 caption", + "properties": [ + { + "name": "By", + "text": "Person 45", + "href": "https://custom.url/123/45" + } + ], + "icon": "https://custom.url/123/22.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_22", + "application": { + "name": "Photos", + "id": "123456" + }, + "created_time": "2013-07-26T22:44:58+0000", + "updated_time": "2013-07-26T22:44:58+0000" + }, + { + "id": "123_23", + "from": { + "category": "Teacher", + "name": "Person 23", + "id": "23" + }, + "message": "Dummy message Person 23", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/23" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:44:57+0000", + "updated_time": "2013-07-26T22:44:57+0000" + }, + { + "id": "24_10151496285490925", + "from": { + "name": "Person 24", + "id": "24" + }, + "message": "Dummy message Person 24", + "story": "Person 24 shared photo.", + "story_tags": { + "0": [ + { + "id": "24", + "name": "Person 24", + "offset": 0, + "length": 30, + "type": "user" + } + ], + "38": [ + { + "id": "86", + "name": "Person 86", + "offset": 38, + "length": 14, + "type": "user" + } + ] + }, + "picture": "https://custom.url/123/24.jpg", + "link": "https://link.url/123/23", + "name": "Person 86 Photos", + "caption": "Person 24 Caption", + "properties": [ + { + "name": "By", + "text": "Person 86", + "href": "https://custom.url/123/86" + } + ], + "icon": "https://custom.url/123/24.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_24", + "application": { + "name": "Links", + "id": "654321" + }, + "created_time": "2013-07-26T22:44:50+0000", + "updated_time": "2013-07-26T22:44:50+0000" + } + ], + "paging": { + "previous": "https://custom.url/previous", + "next": "https://custom.url/next" + } +} \ No newline at end of file
diff --git a/impl/src/test/resources/facebook2.json b/impl/src/test/resources/facebook2.json new file mode 100644 index 0000000..b57b1ed --- /dev/null +++ b/impl/src/test/resources/facebook2.json
@@ -0,0 +1,555 @@ +{ + "data": [ + { + "id": "123_1", + "from": { + "name": "Person 1", + "id": "1" + }, + "message": "Dummy message Person 1", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:57:09+0000", + "updated_time": "2013-07-26T22:57:09+0000" + }, + { + "id": "123_2", + "from": { + "name": "Person 2", + "id": "2" + }, + "message": "Dummy message Person 2", + "picture": "https://custom.url/123/2.jpg", + "link": "https://link.url/123/2", + "source": "https://source.url/123/2", + "name": "Person 2", + "icon": "https://custom.url/123/2.gif", + "privacy": { + "value": "" + }, + "type": "video", + "application": { + "name": "Share_bookmarklet", + "id": "234567" + }, + "created_time": "2013-07-26T22:57:08+0000", + "updated_time": "2013-07-26T22:57:08+0000" + }, + { + "id": "123_3", + "from": { + "category": "Community", + "name": "Group 3", + "id": "3" + }, + "message": "Dummy message Group 3", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/3" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for Android", + "namespace": "fbandroid", + "id": "456789" + }, + "created_time": "2013-07-26T22:57:05+0000", + "updated_time": "2013-07-26T22:57:05+0000" + }, + { + "id": "123_4", + "from": { + "name": "Person 4", + "id": "4" + }, + "message": "Dummy message Person 4", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for Android", + "namespace": "fbandroid", + "id": "456789" + }, + "created_time": "2013-07-26T22:57:00+0000", + "updated_time": "2013-07-26T22:57:00+0000" + }, + { + "id": "123_5", + "from": { + "name": "Person 5", + "id": "5" + }, + "message": "Dummy message Person 5", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:56:58+0000", + "updated_time": "2013-07-26T22:56:58+0000" + }, + { + "id": "123_6", + "from": { + "name": "Person 6", + "id": "6" + }, + "message": "Dummy message Person 6", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for iPhone", + "namespace": "fbiphone", + "id": "23456" + }, + "created_time": "2013-07-26T22:56:54+0000", + "updated_time": "2013-07-26T22:56:54+0000" + }, + { + "id": "123_7", + "from": { + "name": "Person 7", + "id": "7" + }, + "message": "Dummy message Person 7", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "123456" + }, + "created_time": "2013-07-26T22:56:47+0000", + "updated_time": "2013-07-26T22:56:47+0000" + }, + { + "id": "123_8", + "from": { + "name": "Person 8", + "id": "8" + }, + "message": "Dummy message Person 8", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:56:45+0000", + "updated_time": "2013-07-26T22:56:45+0000" + }, + { + "id": "123_9", + "from": { + "name": "Person 9", + "id": "9" + }, + "message": "Dummy message Person 9", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for Android", + "namespace": "fbandroid", + "id": "456789" + }, + "created_time": "2013-07-26T22:56:44+0000", + "updated_time": "2013-07-26T22:56:44+0000" + }, + { + "id": "123_10", + "from": { + "name": "Person 10", + "id": "10" + }, + "message": "Dummy message Person 10", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for Android", + "namespace": "fbandroid", + "id": "456789" + }, + "created_time": "2013-07-26T22:56:36+0000", + "updated_time": "2013-07-26T22:56:36+0000" + }, + { + "id": "123_11", + "from": { + "name": "Person 11", + "id": "11" + }, + "message": "Dummy message Person 11", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "123456" + }, + "created_time": "2013-07-26T22:56:32+0000", + "updated_time": "2013-07-26T22:56:32+0000" + }, + { + "id": "123_12", + "from": { + "name": "Person 12", + "id": "12" + }, + "message": "Dummy message Person 12", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:56:27+0000", + "updated_time": "2013-07-26T22:56:27+0000" + }, + { + "id": "123_13", + "from": { + "category": "Bank/financial institution", + "name": "Group 13", + "id": "13" + }, + "message": "Dummy message Group 13", + "actions": [ + { + "name": "Comment", + "link": "https://link.url/123/23" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "PostCron", + "namespace": "postcron", + "id": "159357" + }, + "created_time": "2013-07-26T22:56:26+0000", + "updated_time": "2013-07-26T22:56:26+0000" + }, + { + "id": "123_14", + "from": { + "name": "Person 14", + "id": "14" + }, + "to": { + "data": [ + { + "name": "Person 99", + "id": "99" + }, + { + "name": "Person 98", + "id": "98" + } + ] + }, + "message": "Dummy message Person 14", + "message_tags": { + "0": [ + { + "id": "99", + "name": "Person 99", + "type": "user", + "offset": 0, + "length": 21 + } + ], + "159": [ + { + "id": "98", + "name": "Person 98", + "type": "user", + "offset": 159, + "length": 26 + } + ] + }, + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:56:16+0000", + "updated_time": "2013-07-26T22:56:16+0000" + }, + { + "id": "123_15", + "from": { + "name": "Person 15", + "id": "15" + }, + "message": "Dummy message Person 15", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:56:15+0000", + "updated_time": "2013-07-26T22:56:15+0000" + }, + { + "id": "123_16", + "from": { + "category": "Just for fun", + "name": "Group 16", + "id": "16" + }, + "message": "Dummy message Group 16", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/16" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "123456" + }, + "created_time": "2013-07-26T22:56:14+0000", + "updated_time": "2013-07-26T22:56:14+0000", + "likes": { + "data": [ + { + "id": "97", + "name": "Person 97" + } + ], + "paging": { + "cursors": { + "after": "MTAwMDAzMDQzNDM5MDQ5", + "before": "MTAwMDAzMDQzNDM5MDQ5" + } + } + } + }, + { + "id": "123_17", + "from": { + "category": "Community", + "name": "Group 17", + "id": "17" + }, + "message": "Dummy message Group 17", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/17" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Pages Manager for Android", + "namespace": "fbpagemgr_android", + "id": "951753" + }, + "created_time": "2013-07-26T22:56:13+0000", + "updated_time": "2013-07-26T22:56:13+0000" + }, + { + "id": "123_18", + "from": { + "name": "Person 18", + "id": "18" + }, + "message": "Dummy message Person 18", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Facebook for iPad", + "namespace": "fbipad_", + "id": "456789" + }, + "created_time": "2013-07-26T22:56:07+0000", + "updated_time": "2013-07-26T22:56:07+0000" + }, + { + "id": "123_19", + "from": { + "name": "Person 19", + "id": "19" + }, + "message": "Dummy message Person 19", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "123456" + }, + "created_time": "2013-07-26T22:56:04+0000", + "updated_time": "2013-07-26T22:56:04+0000" + }, + { + "id": "123_20", + "from": { + "name": "Person 20", + "id": "20" + }, + "message": "Dummy message Person 20", + "story": "Person 20 shared photo.", + "story_tags": { + "0": [ + { + "id": "20", + "name": "Person 20", + "offset": 0, + "length": 11, + "type": "user" + } + ], + "19": [ + { + "id": "95", + "name": "Group 95", + "offset": 19, + "length": 27, + "type": "page" + } + ] + }, + "picture": "https://custom.url/123/20.jpg", + "link": "https://link.url/123/20", + "name": "Timeline Photos", + "caption": "Person 20 link caption", + "properties": [ + { + "name": "By", + "text": "Group 95", + "href": "https://custom.url/123/95" + } + ], + "icon": "https://custom.url/123/20.gif", + "privacy": { + "value": "" + }, + "type": "photo", + "object_id": "456_20", + "application": { + "name": "Facebook for Android", + "namespace": "fbandroid", + "id": "456789" + }, + "created_time": "2013-07-26T22:56:04+0000", + "updated_time": "2013-07-26T22:56:04+0000" + }, + { + "id": "123_21", + "from": { + "name": "Person 21", + "id": "21" + }, + "message": "Dummy message Person 21", + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:55:56+0000", + "updated_time": "2013-07-26T22:55:56+0000" + }, + { + "id": "123_22", + "from": { + "name": "Person 22", + "id": "22" + }, + "message": "Dummy message Person 22", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "948731" + }, + "created_time": "2013-07-26T22:55:38+0000", + "updated_time": "2013-07-26T22:55:38+0000" + }, + { + "id": "123_23", + "from": { + "name": "Person 23", + "id": "23" + }, + "message": "Dummy message Person 23", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "123456" + }, + "created_time": "2013-07-26T22:55:37+0000", + "updated_time": "2013-07-26T22:55:37+0000" + }, + { + "id": "123_24", + "from": { + "name": "Person 24", + "id": "24" + }, + "message": "Dummy message Person 24", + "privacy": { + "value": "" + }, + "type": "status", + "application": { + "name": "Mobile", + "id": "123456" + }, + "created_time": "2013-07-26T22:55:34+0000", + "updated_time": "2013-07-26T22:55:34+0000" + }, + { + "id": "123_25", + "from": { + "category": "Community", + "name": "Group 25", + "id": "25" + }, + "message": "Dummy message Group 25", + "actions": [ + { + "name": "Comment", + "link": "https://custom.url/123/25" + } + ], + "privacy": { + "value": "" + }, + "type": "status", + "created_time": "2013-07-26T22:55:32+0000", + "updated_time": "2013-07-26T22:55:32+0000" + } + ], + "paging": { + "previous": "https://custom.url/previous", + "next": "https://custom.url/next" + } +} \ No newline at end of file
diff --git a/impl/src/test/resources/jsonmergepatch.json b/impl/src/test/resources/jsonmergepatch.json new file mode 100644 index 0000000..3b90e5f --- /dev/null +++ b/impl/src/test/resources/jsonmergepatch.json
@@ -0,0 +1,103 @@ +[ + { + "target": {}, + "patch": {"a": {"b":"c"}}, + "expected": {"a":{"b":"c"}} + }, + { + "target": {}, + "patch": {"a":{"bb":{"ccc":null}}}, + "expected": {"a":{"bb":{}}} + }, + { + "target": {"a":"foo"}, + "patch": "bar", + "expected": "bar" + }, + { + "target": {"a":"foo"}, + "patch": null, + "expected": null + }, + { + "target": {"a": {"b":"c"}}, + "patch": {"a": {"b":"d", "c":null}}, + "expected": {"a": {"b":"d"}} + }, + { + "target": { "c": "d" }, + "patch": { "a": "b" }, + "expected": { "a": "b", "c": "d" } + }, + { + "target": { "a": { "d": 2 } }, + "patch": { "a": { "d": 1 } }, + "expected": { "a": { "d": 1 } } + }, + { + "target": { "a": "b", "c": "d" }, + "patch": { "c": null }, + "expected": { "a": "b" } + }, + { + "target": { "a": { "b": "c", "d": null} }, + "patch": { "a": { "d": null} }, + "expected": { "a": { "b": "c" } } + }, + { + "target": { + "a": { "b": "c" }, + "d": "e" + }, + "patch": { + "a": 1000010002020389.8787987983 + }, + "expected": { + "a": 1000010002020389.8787987983, + "d": "e" + } + }, + { + "target": { "a": "b" }, + "patch": { "c": [ null ] }, + "expected": { "a": "b", "c": [ null ] } + }, + { + "target": { "a": { "b": null, "d": 3}, "e": -1 }, + "patch": { "a": { "b": "c", "d": null } }, + "expected": { "a": { "b": "c" }, "e": -1 } + }, + { + "target": [1,2], + "patch": { "a": "b", "c": null }, + "expected": { "a": "b"} + }, + { + "target": { + "title": "Goodbye!", + "author": { + "givenName": "John", + "familyName": "Doe" + }, + "tags": [ "example", "sample" ], + "content": "This will be unchanged" + }, + "patch": { + "title": "Hello!", + "phoneNumber": "+01-123-456-7890", + "author": { + "familyName": null + }, + "tags": [ "example" ] + }, + "expected": { + "title": "Hello!", + "author": { + "givenName": "John" + }, + "tags": [ "example" ], + "content": "This will be unchanged", + "phoneNumber": "+01-123-456-7890" + } + } +] \ No newline at end of file
diff --git a/impl/src/test/resources/jsonmergepatchdiff.json b/impl/src/test/resources/jsonmergepatchdiff.json new file mode 100644 index 0000000..ac6c91d --- /dev/null +++ b/impl/src/test/resources/jsonmergepatchdiff.json
@@ -0,0 +1,60 @@ +[ + { + "original": { + "title": "Goodbye!", + "author": { + "givenName": "John", + "familyName": "Doe" + }, + "tags": [ "example", "sample" ], + "content": "This will be unchanged" + }, + "expected": { + "title": "Hello!", + "phoneNumber": "+01-123-456-7890", + "author": { + "familyName": null + }, + "tags": [ "example" ] + }, + "target": { + "title": "Hello!", + "author": { + "givenName": "John" + }, + "tags": [ "example" ], + "content": "This will be unchanged", + "phoneNumber": "+01-123-456-7890" + } + }, + { + "original": {}, + "expected": {"a": {"b":"c"}}, + "target": {"a":{"b":"c"}} + }, + { + "original": {"a":"foo"}, + "expected": "bar", + "target": "bar" + }, + { + "original": {"a":"foo"}, + "expected": null, + "target": null + }, + { + "original": { "c": "d" }, + "expected": { "a": "b" }, + "target": { "a": "b", "c": "d" } + }, + { + "original": { "a": { "d": 2 } }, + "expected": { "a": { "d": 1 } }, + "target": { "a": { "d": 1 } } + }, + { + "original": { "a": "b", "c": "d" }, + "expected": { "c": null }, + "target": { "a": "b" } + } +] \ No newline at end of file
diff --git a/impl/src/test/resources/jsonpatch.json b/impl/src/test/resources/jsonpatch.json new file mode 100644 index 0000000..4db4794 --- /dev/null +++ b/impl/src/test/resources/jsonpatch.json
@@ -0,0 +1,219 @@ +[ + { + "op": { "op": "test", "path": "/a/1", "value": "hello" }, + "target": { "a": [ null, "hello", "world" ] }, + "expected": { "a": [ null, "hello", "world" ] } + }, + { + "op": { "op": "test", "path": "/x", "value": {} }, + "target": [ 1, 2 ], + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "test", "path": "", "value": true }, + "target": [ 1, 2 ], + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "test", "path": "/x", "value": -30.000 }, + "target": { "x": -29.020 }, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "replace", "path": "", "value": false }, + "target": { "x": { "a": "b", "y": {} } }, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "replace", "path": "/x/y", "value": "hello" }, + "target": { "x": { "a": "b", "y": {} } }, + "expected": { "x": { "a": "b", "y": "hello" } } + }, + { + "op": { "op": "replace", "path": "/0/2", "value": "x" }, + "target": [ [ "a", "b", "c"], "d", "e" ], + "expected": [ [ "a", "b", "x" ], "d", "e" ] + }, + { + "op": { "op": "replace", "path": "/x/0", "value": null }, + "target": { "x": [ "y", "z" ], "foo": "bar" }, + "expected": { "x": [ null, "z" ], "foo": "bar" } + }, + { + "op": { "op": "replace", "path": "/x/y", "value": 42 }, + "target": { "x": {} }, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "remove", "path": "/x/y" }, + "target": { "x": { "a": "b", "y": {} } }, + "expected": { "x": { "a": "b" } } + }, + { + "op": { "op": "remove", "path": "/0/2" }, + "target": [ [ "a", "b", "c"], "d", "e" ], + "expected": [ [ "a", "b" ], "d", "e" ] + }, + { + "op": { "op": "remove", "path": "/x/0" }, + "target": { "x": [ "y", "z" ], "foo": "bar" }, + "expected": { "x": [ "z" ], "foo": "bar" } + }, + { + "op": { "op": "remove", "path": "/x/y" }, + "target": { "x": {} }, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "move", "from": "/x/a", "path": "/x/b" }, + "target": { "x": { "a": "helo" } }, + "expected": { "x": { "b": "helo" } } + }, + { + "op": { "op": "move", "from": "/x/a", "path": "/x/a" }, + "target": { "x": { "a": "helo" } }, + "expected": { "x": { "a": "helo" } } + }, + { + "op": { "op": "move", "from": "/0", "path": "/0/x" }, + "target": [ "victim", {}, {} ], + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "move", "from": "/0", "path": "/-" }, + "target": [ 0, 1, 2 ], + "expected": [ 1, 2, 0 ] + }, + { + "op": { "op": "move", "from": "/a", "path": "/b/2" }, + "target": { "a": "helo", "b": [ 1, 2, 3, 4 ] }, + "expected": { "b": [ 1, 2, "helo", 3, 4 ] } + }, + { + "op": { "op": "move", "from": "/a", "path": "/a/b" }, + "target": {}, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "move", "from": "/a", "path": "/b/c" }, + "target": { "a": "b" }, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "move", "from": "/x/a", "path": "/x/c" }, + "target": { "x": { "b": "helo" } }, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "copy", "from": "/a", "path": "/b" }, + "target": { "a": 1 }, + "expected": { "a": 1, "b": 1 } + }, + { + "op": { "op": "copy", "from": "/a", "path": "/b" }, + "target": { "a": 1, "b": false }, + "expected": { "a": 1, "b": 1 } + }, + { + "op": { "op": "copy", "from": "/0", "path": "/-" }, + "target": [ 1, 2, 3, 4 ], + "expected": [ 1, 2, 3, 4, 1 ] + }, + { + "op": { "op": "copy", "from": "/0", "path": "/0" }, + "target": [ true ], + "expected": [ true, true ] + }, + { + "op": { "op": "copy", "from": "/a", "path": "/b" }, + "target": {}, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "copy", "from": "/a", "path": "/b/c" }, + "target": { "a": 1 }, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "add", "path": "/a/b/c", "value": 1 }, + "target": { "a": "b" }, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "add", "path": "/~1", "value": 1 }, + "target": [], + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "add", "path": "/3", "value": 1 }, + "target": [ 1, 2 ], + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "add", "path": "/-2", "value": 1 }, + "target": [ 1, 2 ], + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "add", "path": "/foo/f", "value": "bar" }, + "target": { "foo": "bar" }, + "exception": "jakarta.json.JsonException" + }, + { + "op": { "op": "add", "path": "/a", "value": "b" }, + "target": {}, + "expected": { "a": "b" } + }, + { + "op": { "op": "add", "path": "/a", "value": 1 }, + "target": { "a": "b" }, + "expected": { "a": 1 } + }, + { + "op": { "op": "add", "path": "/array/-", "value": 1 }, + "target": { "array": [ 2, null, {}, 1 ] }, + "expected": { "array": [ 2, null, {}, 1, 1 ] } + }, + { + "op": { "op": "add", "path": "/array/2", "value": "hello" }, + "target": { "array": [ 2, null, {}, 1] }, + "expected": { "array": [ 2, null, "hello", {}, 1 ] } + }, + { + "op": { "op": "add", "path": "/obj/inner/b", "value": [ 1, 2 ] }, + "target": { + "obj": { + "inner": { + "a": "hello" + } + } + }, + "expected": { + "obj": { + "inner": { + "a": "hello", + "b": [ 1, 2 ] + } + } + } + }, + { + "op": { "op": "add", "path": "/obj/inner/b", "value": [ 1, 2 ] }, + "target": { + "obj": { + "inner": { + "a": "hello", + "b": "world" + } + } + }, + "expected": { + "obj": { + "inner": { + "a": "hello", + "b": [ 1, 2 ] + } + } + } + } +]
diff --git a/impl/src/test/resources/jsonpatchdiff.json b/impl/src/test/resources/jsonpatchdiff.json new file mode 100644 index 0000000..d4aa8fe --- /dev/null +++ b/impl/src/test/resources/jsonpatchdiff.json
@@ -0,0 +1,169 @@ +[ + { + "original": {"a":"b"}, + "target": {"a":"b"}, + "expected": [] + }, + { + "original": [ 1, 2, 3 ], + "target": [ 1, 2, 3, 4, 5 ], + "expected": [ + {"op":"add","path":"/3","value":4}, + {"op":"add","path":"/4","value":5} + ] + }, + { + "original": [1,2,3,4,5], + "target": [1,3,4], + "expected": [ + { "op": "remove", "path": "/4"}, + { "op": "remove", "path": "/1"} + ] + }, + { + "original": [1,2,3,4,5,6], + "target": [1,7,3,4,8,5], + "expected": [ + { "op": "remove", "path": "/5"}, + { "op": "replace", "path": "/1", "value": 7}, + { "op": "add", "path": "/4", "value": 8} + ] + }, + { + "original": [ 1, 2, 3 ], + "target": [ 1 ], + "expected": [ + { "op": "remove", "path": "/2" }, + { "op": "remove", "path": "/1" } + ] + }, + { + "original": { "a": "b", "c": "d" }, + "target": { "a": "b" }, + "expected": [ + { "op": "remove", "path": "/c" } + ] + }, + { + "original": { "a": 1 }, + "target": { "a": 1, "c": 2, "b": 3, "d": 4 }, + "expected": [ + { "op": "add", "path": "/c", "value": 2 }, + { "op": "add", "path": "/b", "value": 3 }, + { "op": "add", "path": "/d", "value": 4 } + ] + }, + { + "original": { "a": null }, + "target": { "a": 6 }, + "expected": [ + { "op": "replace", "path": "/a", "value": 6 } + ] + }, + { + "original": [ 1, 2, 3 ], + "target": { "hello": "world" }, + "expected": [ + { "op": "replace", "path": "", "value": { "hello": "world" } } + ] + }, + { + "original": { + "a": "b", + "c": { + "d": "e" + } + }, + "target": { + "a": "b", + "c": { + "d": 1, + "e": "f" + } + }, + "expected": [ + { "op": "replace", "path": "/c/d", "value": 1 }, + { "op": "add", "path": "/c/e", "value": "f" } + ] + }, + { + "original": { + "a": [ 1, 2, 3 ] + }, + "target": { + "a": [ "b", 2, 3, 4 ] + }, + "expected": [ + { "op": "replace", "path": "/a/0", "value":"b" }, + { "op": "add", "path": "/a/3", "value":4 } + ] + }, + { + "original": [ { "a": "b" }, "foo", { "bar": null } ], + "target": [ { "a": "b", "c": "d" }, "foo", { "bar": "baz" } ], + "expected": [ + { "op": "replace", "path": "/2/bar", "value": "baz" }, + { "op": "add", "path": "/0/c", "value": "d" } + ] + }, + { + "original": [ 1, [ 2, 3 ], 4 ], + "target": [ "x", [ 2, 3, "y" ], 4 ], + "expected": [ + { "op": "add", "path": "/1/2", "value": "y" }, + { "op": "replace", "path": "/0", "value": "x" } + ] + }, + { + "original": { "a": "b" }, + "target": { "c": "b" }, + "expected": [ + { "op": "remove", "path": "/a"}, + { "op": "add", "path": "/c", "value": "b"} + ] + }, + { + "original": {"a": "c"}, + "target": {"a": "c", "d": "c"}, + "expected": [ + { "op": "add", "path": "/d", "value": "c" } + ] + }, + { + "original": [-1, 0, 1, 3, 4], + "target": [5, 0], + "expected": [ + { "path" : "/4", "op" : "remove"}, + { "path" : "/3", "op" : "remove"}, + { "path" : "/2", "op" : "remove"}, + { "value" : 5, "path" : "/0", "op" : "replace" } + ] + }, + { + "original": [0], + "target": [0, 1, 2, 3, 4], + "expected": [ + { "path" : "/1", "value" : 1, "op" : "add" }, + { "path" : "/2", "value" : 2, "op" : "add" }, + { "value" : 3, "path" : "/3", "op" : "add" }, + { "op" : "add", "path" : "/4", "value" : 4 } + ] + }, + { + "original": [0, 2, 4], + "target": [0, 1, 2, 3, 4], + "expected": [ + { "path" : "/1", "value" : 1, "op" : "add" }, + { "value" : 3, "op" : "add", "path" : "/3" } + ] + }, + { + "original": {"a/b": "c", "e/f": "i"}, + "target": {"a/b": "d", "f/g": "i"}, + "expected": [ + { "op": "replace", "path": "/a~1b", "value": "d" }, + { "op": "remove", "path":"/e~1f" }, + { "op": "add", "path":"/f~1g", "value":"i" } + ] + } +]
diff --git a/impl/src/test/resources/rfc6901.json b/impl/src/test/resources/rfc6901.json new file mode 100644 index 0000000..170147b --- /dev/null +++ b/impl/src/test/resources/rfc6901.json
@@ -0,0 +1,20 @@ + { + "foo": ["bar", "baz"], + "": 0, + "a/b": 1, + "c%d": 2, + "e^f": 3, + "g|h": 4, + "i\\j": 5, + "k\"l": 6, + " ": 7, + "m~n": 8, + "o" : null, + "p": { + "q":"r" + }, + "s": [ { + "t":"u" + } + ] + } \ No newline at end of file
diff --git a/impl/src/test/resources/twitter.json b/impl/src/test/resources/twitter.json new file mode 100644 index 0000000..677f2b9 --- /dev/null +++ b/impl/src/test/resources/twitter.json
@@ -0,0 +1,2 @@ +{"statuses":[{"metadata":{"result_type":"recent","iso_language_code":"de"},"created_at":"Fri Jul 26 19:31:26 +0000 2013","id":360844831439855616,"id_str":"360844831439855616","text":"Hiring ••► Pre-Sales Consultant ☛ http://t.co/fjlOd8PhcQ #Java #JUnit #Python #PHP #XML #XSLT #SOAP #REST #SAML #Node","source":"<a href=\"http://www.socialoomph.com\" rel=\"nofollow\">SocialOomph</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":93646439,"id_str":"93646439","name":"Paul Pleus","screen_name":"IER_Recruiting","location":"Worldwide","description":"International Executive Recruiting – IER, Xing, Linkedin, Recruiting, Recruiter, Headhunter Personalberater, Job, Jobs, Stellenangebot, Manager","url":"http://t.co/GtcxFsUyI3","entities":{"url":{"urls":[{"url":"http://t.co/GtcxFsUyI3","expanded_url":"http://www.ier-network.com","display_url":"ier-network.com","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":17822,"friends_count":15829,"listed_count":119,"created_at":"Mon Nov 30 15:02:59 +0000 2009","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":26733,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"0099B9","profile_background_image_url":"http://a0.twimg.com/profile_background_images/216930247/pleus_final_logo_KUGEL.jpg","profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/216930247/pleus_final_logo_KUGEL.jpg","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/1270812893/Final_198x146_normal.jpg","profile_image_url_https":"https://si0.twimg.com/profile_images/1270812893/Final_198x146_normal.jpg","profile_link_color":"0099B9","profile_sidebar_border_color":"5ED4DC","profile_sidebar_fill_color":"95E8EC","profile_text_color":"3C3940","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"Java","indices":[57,62]},{"text":"JUnit","indices":[63,69]},{"text":"Python","indices":[70,77]},{"text":"PHP","indices":[78,82]},{"text":"XML","indices":[83,87]},{"text":"XSLT","indices":[88,93]},{"text":"SOAP","indices":[94,99]},{"text":"REST","indices":[100,105]},{"text":"SAML","indices":[106,111]},{"text":"Node","indices":[112,117]}],"symbols":[],"urls":[{"url":"http://t.co/fjlOd8PhcQ","expanded_url":"http://bit.ly/19I4P7E","display_url":"bit.ly/19I4P7E","indices":[34,56]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"de"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:30:39 +0000 2013","id":360844632520798209,"id_str":"360844632520798209","text":"Death toll reaches 15 for #Indonesian asylum seeker boat that capsized off the coast of west #Java http://t.co/4rGk0LO9F8","source":"<a href=\"http://www.tweetdeck.com\" rel=\"nofollow\">TweetDeck</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":90407341,"id_str":"90407341","name":"CSIS Southeast Asia","screen_name":"SoutheastAsiaDC","location":"Washington, DC","description":"The Sumitro Chair for Southeast Asia Studies @CSIS is the premier forum for sustained elevated policy dialogue on Southeast Asia and US interests in the region.","url":"http://t.co/1bcQU6sG1V","entities":{"url":{"urls":[{"url":"http://t.co/1bcQU6sG1V","expanded_url":"http://bit.ly/csis-seap","display_url":"bit.ly/csis-seap","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":8127,"friends_count":523,"listed_count":427,"created_at":"Mon Nov 16 14:51:00 +0000 2009","favourites_count":16,"utc_offset":-14400,"time_zone":"Eastern Time (US & Canada)","geo_enabled":false,"verified":false,"statuses_count":12019,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"B2DFDA","profile_background_image_url":"http://a0.twimg.com/profile_background_images/669153955/be1298700d512cfdd3734a677a587095.gif","profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/669153955/be1298700d512cfdd3734a677a587095.gif","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/2648645038/e06eb649efb4030845d4cbf47d41651b_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/2648645038/e06eb649efb4030845d4cbf47d41651b_normal.jpeg","profile_banner_url":"https://pbs.twimg.com/profile_banners/90407341/1371826204","profile_link_color":"93A644","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"FFFFFF","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"Indonesian","indices":[26,37]},{"text":"Java","indices":[93,98]}],"symbols":[],"urls":[{"url":"http://t.co/4rGk0LO9F8","expanded_url":"http://fxn.ws/1c7VZ2F","display_url":"fxn.ws/1c7VZ2F","indices":[99,121]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:30:15 +0000 2013","id":360844531593261057,"id_str":"360844531593261057","text":"Senior Java Developer w/ #Java #Software skills Addison @p2people http://t.co/Fc9UlSdyWj","source":"<a href=\"http://www.p2people.co.uk\" rel=\"nofollow\">p2people</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":551581457,"id_str":"551581457","name":"p2p WebMobileIT","screen_name":"p2pWebMobileIt","location":"Stevenage | Hertfordshire","description":"Web, Mobile & IT micro #outsourcing and #freelance jobs at p2people","url":"http://t.co/OxLhyJdlxw","entities":{"url":{"urls":[{"url":"http://t.co/OxLhyJdlxw","expanded_url":"http://www.p2people.co.uk","display_url":"p2people.co.uk","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":712,"friends_count":3,"listed_count":44,"created_at":"Thu Apr 12 05:07:17 +0000 2012","favourites_count":0,"utc_offset":3600,"time_zone":"London","geo_enabled":false,"verified":false,"statuses_count":88202,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://a0.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/2099631495/p2people_logo_48x48_normal.png","profile_image_url_https":"https://si0.twimg.com/profile_images/2099631495/p2people_logo_48x48_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"Java","indices":[25,30]},{"text":"Software","indices":[31,40]}],"symbols":[],"urls":[{"url":"http://t.co/Fc9UlSdyWj","expanded_url":"http://bit.ly/175ch6w","display_url":"bit.ly/175ch6w","indices":[66,88]}],"user_mentions":[{"screen_name":"p2people","name":"p2people","id":22741835,"id_str":"22741835","indices":[56,65]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:30:00 +0000 2013","id":360844471761502209,"id_str":"360844471761502209","text":"Took 658ms to processing 200 tweets #JAVA #APPENGINE #1374867000804","source":"<a href=\"http://google.co.id/\" rel=\"nofollow\">You Can't Be Wrong</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1186398894,"id_str":"1186398894","name":"You Can't Be Wrong","screen_name":"YouCantBeWrong","location":"@tegaralaga's mind","description":"User generated content text game based on Twitter. For more information send your email to tegaralaga(at)live(dot)com","url":"http://t.co/Jto68Xkf","entities":{"url":{"urls":[{"url":"http://t.co/Jto68Xkf","expanded_url":"http://google.co.id/","display_url":"google.co.id","indices":[0,20]}]},"description":{"urls":[]}},"protected":false,"followers_count":8,"friends_count":1,"listed_count":1,"created_at":"Sat Feb 16 14:30:21 +0000 2013","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":22815,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://a0.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/3261474447/f3cabcc48d277be37e45ac7b1038d73e_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/3261474447/f3cabcc48d277be37e45ac7b1038d73e_normal.jpeg","profile_banner_url":"https://pbs.twimg.com/profile_banners/1186398894/1361117710","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"JAVA","indices":[36,41]},{"text":"APPENGINE","indices":[42,52]}],"symbols":[],"urls":[],"user_mentions":[]},"favorited":false,"retweeted":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:29:22 +0000 2013","id":360844310297591811,"id_str":"360844310297591811","text":"RT @ECBader: Some interesting open source #Java projects from #Esri http://t.co/1pvAEzkV9r. Geometry API is worth checking out! https://t.c…","source":"<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":11640022,"id_str":"11640022","name":"Philip Heede","screen_name":"pheede","location":"Redlands, CA","description":"Transplanted Dane using GIS at Esri w/.NET/XAML/Geoprocessing/Python/ArcObjects/Network Analyst/.. Disclaimer: all opinions, comments are my own, blah blah..","url":null,"entities":{"description":{"urls":[]}},"protected":false,"followers_count":355,"friends_count":267,"listed_count":22,"created_at":"Sat Dec 29 20:25:10 +0000 2007","favourites_count":114,"utc_offset":-25200,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":1711,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://a0.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/335064929/n701240139_383204_9480_normal.jpg","profile_image_url_https":"https://si0.twimg.com/profile_images/335064929/n701240139_383204_9480_normal.jpg","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 15:40:13 +0000 2013","id":360786645261352961,"id_str":"360786645261352961","text":"Some interesting open source #Java projects from #Esri http://t.co/1pvAEzkV9r. Geometry API is worth checking out! https://t.co/yEXKNTClKZ","source":"<a href=\"http://www.tweetdeck.com\" rel=\"nofollow\">TweetDeck</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":26422164,"id_str":"26422164","name":"Eric Bader","screen_name":"ECBader","location":"Southern California","description":"Geographer, Musician, Christ-follower, Java dude, Nebraska Cornhusker, Esri Product Management Team - ArcGIS.","url":null,"entities":{"description":{"urls":[]}},"protected":false,"followers_count":614,"friends_count":473,"listed_count":37,"created_at":"Wed Mar 25 03:44:15 +0000 2009","favourites_count":27,"utc_offset":-25200,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":2700,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"1A1B1F","profile_background_image_url":"http://a0.twimg.com/images/themes/theme9/bg.gif","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme9/bg.gif","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/2586630286/dct7znna7xosntblt7jb_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/2586630286/dct7znna7xosntblt7jb_normal.jpeg","profile_link_color":"2FC2EF","profile_sidebar_border_color":"181A1E","profile_sidebar_fill_color":"252429","profile_text_color":"666666","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":2,"favorite_count":0,"entities":{"hashtags":[{"text":"Java","indices":[29,34]},{"text":"Esri","indices":[49,54]}],"symbols":[],"urls":[{"url":"http://t.co/1pvAEzkV9r","expanded_url":"http://esri.github.io/#Java","display_url":"esri.github.io/#Java","indices":[55,77]},{"url":"https://t.co/yEXKNTClKZ","expanded_url":"https://github.com/Esri/geometry-api-java","display_url":"github.com/Esri/geometry-…","indices":[115,138]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},"retweet_count":2,"favorite_count":0,"entities":{"hashtags":[{"text":"Java","indices":[42,47]},{"text":"Esri","indices":[62,67]}],"symbols":[],"urls":[{"url":"http://t.co/1pvAEzkV9r","expanded_url":"http://esri.github.io/#Java","display_url":"esri.github.io/#Java","indices":[68,90]}],"user_mentions":[{"screen_name":"ECBader","name":"Eric Bader","id":26422164,"id_str":"26422164","indices":[3,11]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:29:17 +0000 2013","id":360844289841971200,"id_str":"360844289841971200","text":"Looking for a new IT challenge? Take a look at our job openings http://t.co/MhnnR101cT #atlassian #java #oracle #mobile #infra #jobs","source":"<a href=\"http://www.tweetdeck.com\" rel=\"nofollow\">TweetDeck</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":296655269,"id_str":"296655269","name":"Koen Gillard","screen_name":"KoenGillard","location":"","description":"Sr Java/Oracle Consultant at @Contribute4J. Certified Scrum Master. Big Atlassian enthusiast. Father of 2 great sons. Other interests music/soccer/cycling/...","url":null,"entities":{"description":{"urls":[]}},"protected":false,"followers_count":151,"friends_count":341,"listed_count":4,"created_at":"Wed May 11 05:23:43 +0000 2011","favourites_count":874,"utc_offset":7200,"time_zone":"Brussels","geo_enabled":false,"verified":false,"statuses_count":549,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"ACDED6","profile_background_image_url":"http://a0.twimg.com/images/themes/theme18/bg.gif","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme18/bg.gif","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/3690118960/3bf92c8b7f1398f35e635f0d08bde368_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/3690118960/3bf92c8b7f1398f35e635f0d08bde368_normal.jpeg","profile_link_color":"038543","profile_sidebar_border_color":"EEEEEE","profile_sidebar_fill_color":"F6F6F6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"atlassian","indices":[87,97]},{"text":"java","indices":[98,103]},{"text":"oracle","indices":[104,111]},{"text":"mobile","indices":[112,119]},{"text":"infra","indices":[120,126]},{"text":"jobs","indices":[127,132]}],"symbols":[],"urls":[{"url":"http://t.co/MhnnR101cT","expanded_url":"http://jobs.contribute.be","display_url":"jobs.contribute.be","indices":[64,86]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"in"},"created_at":"Fri Jul 26 19:27:56 +0000 2013","id":360843950518566914,"id_str":"360843950518566914","text":"RT @SKSMediaMalay: Rip-off or investor's dream? You decide...http://t.co/bxk76YXRJM #Bandar #Lampung #java #Sumatra #Banten #Riau #Padang //","source":"<a href=\"http://roundteam.co\" rel=\"nofollow\">RoundTeam</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1596343046,"id_str":"1596343046","name":"Rooms_In_Lowestoft","screen_name":"RoomsLowestoft","location":"Lowestoft, Suffolk, UK","description":"#Rooms #Room to #rent #let in #Lowestoft, #Suffolk, #UK E: lowestoft@niche.me.uk \r\n\r\n#norfolk #greatyarmouth #saxmundham #ipswich #aldeburgh #leiston #tfbuk","url":"https://t.co/aeCwVfy3l0","entities":{"url":{"urls":[{"url":"https://t.co/aeCwVfy3l0","expanded_url":"https://twitter.com/RoomsLowestoft","display_url":"twitter.com/RoomsLowestoft","indices":[0,23]}]},"description":{"urls":[]}},"protected":false,"followers_count":963,"friends_count":1742,"listed_count":14,"created_at":"Mon Jul 15 17:23:58 +0000 2013","favourites_count":182,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":9095,"lang":"en-gb","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://a0.twimg.com/profile_background_images/378800000024425110/a2acf9f2d9bf8f8c90cb24910a71c037.jpeg","profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/378800000024425110/a2acf9f2d9bf8f8c90cb24910a71c037.jpeg","profile_background_tile":true,"profile_image_url":"http://a0.twimg.com/profile_images/378800000138549193/b276cf4d94b9c96e5b61c92f9864615f_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/378800000138549193/b276cf4d94b9c96e5b61c92f9864615f_normal.jpeg","profile_banner_url":"https://pbs.twimg.com/profile_banners/1596343046/1373917379","profile_link_color":"0084B4","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"metadata":{"result_type":"recent","iso_language_code":"in"},"created_at":"Fri Jul 26 19:20:50 +0000 2013","id":360842165292773376,"id_str":"360842165292773376","text":"Rip-off or investor's dream? You decide...http://t.co/bxk76YXRJM #Bandar #Lampung #java #Sumatra #Banten #Riau #Padang //","source":"<a href=\"http://www.hootsuite.com\" rel=\"nofollow\">HootSuite</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1449573356,"id_str":"1449573356","name":"SKS Media Malaysia","screen_name":"SKSMediaMalay","location":"Kuala Lumpur","description":"Pemasaran syarikat perkhidmatan.\r\n\r\n#teamfollowback #tfb #tfbjp #autofollow #followback","url":"https://t.co/nfmdo6g6HC","entities":{"url":{"urls":[{"url":"https://t.co/nfmdo6g6HC","expanded_url":"https://twitter.com/SKSMediaMalay","display_url":"twitter.com/SKSMediaMalay","indices":[0,23]}]},"description":{"urls":[]}},"protected":false,"followers_count":1048,"friends_count":877,"listed_count":27,"created_at":"Wed May 22 18:07:31 +0000 2013","favourites_count":166,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":8006,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://a0.twimg.com/profile_background_images/874883247/77db35ff9cff8c42d2ef4c2bcd22df35.jpeg","profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/874883247/77db35ff9cff8c42d2ef4c2bcd22df35.jpeg","profile_background_tile":true,"profile_image_url":"http://a0.twimg.com/profile_images/3695357949/77db35ff9cff8c42d2ef4c2bcd22df35_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/3695357949/77db35ff9cff8c42d2ef4c2bcd22df35_normal.jpeg","profile_link_color":"0084B4","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":1,"favorite_count":0,"entities":{"hashtags":[{"text":"Bandar","indices":[65,72]},{"text":"Lampung","indices":[73,81]},{"text":"java","indices":[82,87]},{"text":"Sumatra","indices":[88,96]},{"text":"Banten","indices":[97,104]},{"text":"Riau","indices":[105,110]},{"text":"Padang","indices":[111,118]}],"symbols":[],"urls":[{"url":"http://t.co/bxk76YXRJM","expanded_url":"http://tinyurl.com/dxxrao5","display_url":"tinyurl.com/dxxrao5","indices":[42,64]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"in"},"retweet_count":1,"favorite_count":0,"entities":{"hashtags":[{"text":"Bandar","indices":[84,91]},{"text":"Lampung","indices":[92,100]},{"text":"java","indices":[101,106]},{"text":"Sumatra","indices":[107,115]},{"text":"Banten","indices":[116,123]},{"text":"Riau","indices":[124,129]},{"text":"Padang","indices":[130,137]}],"symbols":[],"urls":[{"url":"http://t.co/bxk76YXRJM","expanded_url":"http://tinyurl.com/dxxrao5","display_url":"tinyurl.com/dxxrao5","indices":[61,83]}],"user_mentions":[{"screen_name":"SKSMediaMalay","name":"SKS Media Malaysia","id":1449573356,"id_str":"1449573356","indices":[3,17]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"in"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:25:27 +0000 2013","id":360843324011184128,"id_str":"360843324011184128","text":"#Java #Developer #BackEnd position open in #Dallas TX. #BED #BE #JavaDev Apply Online Today! - http://t.co/oVDyhoR65M","source":"<a href=\"http://www.hootsuite.com\" rel=\"nofollow\">HootSuite</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":52097984,"id_str":"52097984","name":"InSource Group","screen_name":"InSourcegroup","location":"Dallas, Texas","description":"Technical Resource & Contract Staffing Provider with offices in Dallas, Fort Worth, and Houston.","url":"http://t.co/IyUTPyeCMm","entities":{"url":{"urls":[{"url":"http://t.co/IyUTPyeCMm","expanded_url":"http://www.insourcegroup.com","display_url":"insourcegroup.com","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":1712,"friends_count":1899,"listed_count":63,"created_at":"Mon Jun 29 16:03:36 +0000 2009","favourites_count":81,"utc_offset":-18000,"time_zone":"Central Time (US & Canada)","geo_enabled":false,"verified":false,"statuses_count":43289,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"FFFFFF","profile_background_image_url":"http://a0.twimg.com/profile_background_images/57804915/nvoffice.br.jpg","profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/57804915/nvoffice.br.jpg","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/1109935707/insource-fb_normal.gif","profile_image_url_https":"https://si0.twimg.com/profile_images/1109935707/insource-fb_normal.gif","profile_banner_url":"https://pbs.twimg.com/profile_banners/52097984/1369854759","profile_link_color":"0083FF","profile_sidebar_border_color":"000000","profile_sidebar_fill_color":"7ABAE6","profile_text_color":"000000","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"Java","indices":[0,5]},{"text":"Developer","indices":[6,16]},{"text":"BackEnd","indices":[17,25]},{"text":"Dallas","indices":[43,50]},{"text":"BED","indices":[55,59]},{"text":"BE","indices":[60,63]},{"text":"JavaDev","indices":[64,72]}],"symbols":[],"urls":[{"url":"http://t.co/oVDyhoR65M","expanded_url":"http://ow.ly/nkcSS","display_url":"ow.ly/nkcSS","indices":[95,117]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:22:18 +0000 2013","id":360842533410045954,"id_str":"360842533410045954","text":"3,2,1... Stir and energy will be served! #coffee #addict #givemecaffine #java http://t.co/OjGso3pbPt","source":"<a href=\"http://instagram.com\" rel=\"nofollow\">Instagram</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":17855557,"id_str":"17855557","name":"Heather Cereghino","screen_name":"HeatherCinOC","location":"Orange County, CA","description":"Social media-lite, creative writing (beach + laptop = bliss), Event Planner, PR, cook in the making, love the outdoors, traveling & shoes. PS. I love shoes!","url":null,"entities":{"description":{"urls":[]}},"protected":false,"followers_count":4114,"friends_count":4410,"listed_count":232,"created_at":"Thu Dec 04 01:19:51 +0000 2008","favourites_count":218,"utc_offset":-25200,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":12505,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"B2DFDA","profile_background_image_url":"http://a0.twimg.com/images/themes/theme13/bg.gif","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme13/bg.gif","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/3673021821/693873aafc52e32076ff85d68302ff78_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/3673021821/693873aafc52e32076ff85d68302ff78_normal.jpeg","profile_banner_url":"https://pbs.twimg.com/profile_banners/17855557/1370094052","profile_link_color":"93A644","profile_sidebar_border_color":"EEEEEE","profile_sidebar_fill_color":"FFFFFF","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"coffee","indices":[41,48]},{"text":"addict","indices":[49,56]},{"text":"givemecaffine","indices":[57,71]},{"text":"java","indices":[72,77]}],"symbols":[],"urls":[{"url":"http://t.co/OjGso3pbPt","expanded_url":"http://instagram.com/p/cPZ9yEqwlf/","display_url":"instagram.com/p/cPZ9yEqwlf/","indices":[78,100]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"in"},"created_at":"Fri Jul 26 19:20:50 +0000 2013","id":360842165292773376,"id_str":"360842165292773376","text":"Rip-off or investor's dream? You decide...http://t.co/bxk76YXRJM #Bandar #Lampung #java #Sumatra #Banten #Riau #Padang //","source":"<a href=\"http://www.hootsuite.com\" rel=\"nofollow\">HootSuite</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1449573356,"id_str":"1449573356","name":"SKS Media Malaysia","screen_name":"SKSMediaMalay","location":"Kuala Lumpur","description":"Pemasaran syarikat perkhidmatan.\r\n\r\n#teamfollowback #tfb #tfbjp #autofollow #followback","url":"https://t.co/nfmdo6g6HC","entities":{"url":{"urls":[{"url":"https://t.co/nfmdo6g6HC","expanded_url":"https://twitter.com/SKSMediaMalay","display_url":"twitter.com/SKSMediaMalay","indices":[0,23]}]},"description":{"urls":[]}},"protected":false,"followers_count":1048,"friends_count":877,"listed_count":27,"created_at":"Wed May 22 18:07:31 +0000 2013","favourites_count":166,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":8006,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://a0.twimg.com/profile_background_images/874883247/77db35ff9cff8c42d2ef4c2bcd22df35.jpeg","profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/874883247/77db35ff9cff8c42d2ef4c2bcd22df35.jpeg","profile_background_tile":true,"profile_image_url":"http://a0.twimg.com/profile_images/3695357949/77db35ff9cff8c42d2ef4c2bcd22df35_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/3695357949/77db35ff9cff8c42d2ef4c2bcd22df35_normal.jpeg","profile_link_color":"0084B4","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":1,"favorite_count":0,"entities":{"hashtags":[{"text":"Bandar","indices":[65,72]},{"text":"Lampung","indices":[73,81]},{"text":"java","indices":[82,87]},{"text":"Sumatra","indices":[88,96]},{"text":"Banten","indices":[97,104]},{"text":"Riau","indices":[105,110]},{"text":"Padang","indices":[111,118]}],"symbols":[],"urls":[{"url":"http://t.co/bxk76YXRJM","expanded_url":"http://tinyurl.com/dxxrao5","display_url":"tinyurl.com/dxxrao5","indices":[42,64]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"in"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:20:08 +0000 2013","id":360841988431556609,"id_str":"360841988431556609","text":"Took 8397ms to processing 200 tweets #JAVA #APPENGINE #1374866408704","source":"<a href=\"http://google.co.id/\" rel=\"nofollow\">You Can't Be Wrong</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1186398894,"id_str":"1186398894","name":"You Can't Be Wrong","screen_name":"YouCantBeWrong","location":"@tegaralaga's mind","description":"User generated content text game based on Twitter. For more information send your email to tegaralaga(at)live(dot)com","url":"http://t.co/Jto68Xkf","entities":{"url":{"urls":[{"url":"http://t.co/Jto68Xkf","expanded_url":"http://google.co.id/","display_url":"google.co.id","indices":[0,20]}]},"description":{"urls":[]}},"protected":false,"followers_count":8,"friends_count":1,"listed_count":1,"created_at":"Sat Feb 16 14:30:21 +0000 2013","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":22815,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://a0.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/3261474447/f3cabcc48d277be37e45ac7b1038d73e_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/3261474447/f3cabcc48d277be37e45ac7b1038d73e_normal.jpeg","profile_banner_url":"https://pbs.twimg.com/profile_banners/1186398894/1361117710","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"JAVA","indices":[37,42]},{"text":"APPENGINE","indices":[43,53]}],"symbols":[],"urls":[],"user_mentions":[]},"favorited":false,"retweeted":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:18:09 +0000 2013","id":360841487262547968,"id_str":"360841487262547968","text":"Can’t decide between more #java or #c++","source":"<a href=\"http://tapbots.com/tweetbot\" rel=\"nofollow\">Tweetbot for iOS</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":29063267,"id_str":"29063267","name":"Steven Truesdell","screen_name":"TrueSteve","location":"Denver, CO","description":"Snowboarder. Photographer. Web Designer. Journalist. Music lover. Soon to be Firefighter & EMT","url":"http://t.co/fCPFLstB49","entities":{"url":{"urls":[{"url":"http://t.co/fCPFLstB49","expanded_url":"http://www.steventruesdell.com","display_url":"steventruesdell.com","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":88,"friends_count":144,"listed_count":3,"created_at":"Sun Apr 05 21:02:17 +0000 2009","favourites_count":0,"utc_offset":-21600,"time_zone":"Mountain Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":1792,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"1A1B1F","profile_background_image_url":"http://a0.twimg.com/images/themes/theme9/bg.gif","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme9/bg.gif","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/3637401835/e96f6955cd6bfd3d7bf78002ebdbd0de_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/3637401835/e96f6955cd6bfd3d7bf78002ebdbd0de_normal.jpeg","profile_link_color":"2FC2EF","profile_sidebar_border_color":"181A1E","profile_sidebar_fill_color":"252429","profile_text_color":"666666","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":{"id":"2571b7720cd62ad3","url":"https://api.twitter.com/1.1/geo/id/2571b7720cd62ad3.json","place_type":"city","name":"Highlands Ranch","full_name":"Highlands Ranch, CO","country_code":"US","country":"United States","bounding_box":{"type":"Polygon","coordinates":[[[-105.05306,39.510546],[-104.899484,39.510546],[-104.899484,39.566782],[-105.05306,39.566782]]]},"attributes":{}},"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"java","indices":[26,31]},{"text":"c","indices":[35,37]}],"symbols":[],"urls":[],"user_mentions":[]},"favorited":false,"retweeted":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"pt"},"created_at":"Fri Jul 26 19:17:48 +0000 2013","id":360841400004251648,"id_str":"360841400004251648","text":"RT @maribalbe: No Brasil? Piada! RT @rogerio_gentil: Desenvolvedores em #PHP e #Java ganham até R$ 9 mil http://t.co/Cj6dotO8Be // #souDev","source":"<a href=\"http://www.tweetdeck.com\" rel=\"nofollow\">TweetDeck</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":188855964,"id_str":"188855964","name":"Rodrigo Baron","screen_name":"b4r0n__","location":"Medianeira","description":"Full-stack Rails Developer. Addicts script codes and Internet App Dev. Startup Co-Founder: http://t.co/Vvj2Un84yC","url":"http://t.co/WEJSgUafv6","entities":{"url":{"urls":[{"url":"http://t.co/WEJSgUafv6","expanded_url":"http://about.me/baron.rodrigo","display_url":"about.me/baron.rodrigo","indices":[0,22]}]},"description":{"urls":[{"url":"http://t.co/Vvj2Un84yC","expanded_url":"http://www.saifer.com.br","display_url":"saifer.com.br","indices":[91,113]}]}},"protected":false,"followers_count":121,"friends_count":183,"listed_count":1,"created_at":"Thu Sep 09 19:15:20 +0000 2010","favourites_count":105,"utc_offset":-10800,"time_zone":"Brasilia","geo_enabled":true,"verified":false,"statuses_count":3777,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"FFFFFF","profile_background_image_url":"http://a0.twimg.com/images/themes/theme14/bg.gif","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme14/bg.gif","profile_background_tile":true,"profile_image_url":"http://a0.twimg.com/profile_images/378800000105833766/cfe4372a0fce180e09813ab02f909a4d_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/378800000105833766/cfe4372a0fce180e09813ab02f909a4d_normal.jpeg","profile_link_color":"006DCC","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"EFEFEF","profile_text_color":"333333","profile_use_background_image":false,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"metadata":{"result_type":"recent","iso_language_code":"pt"},"created_at":"Fri Jul 26 14:37:46 +0000 2013","id":360770928357027840,"id_str":"360770928357027840","text":"No Brasil? Piada! RT @rogerio_gentil: Desenvolvedores em #PHP e #Java ganham até R$ 9 mil http://t.co/Cj6dotO8Be // #souDev","source":"<a href=\"http://www.tweetdeck.com\" rel=\"nofollow\">TweetDeck</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":41602902,"id_str":"41602902","name":"Marília Balbé","screen_name":"maribalbe","location":"Florianópolis, Brazil","description":"Certified Scrum Master. MCTS Microsoft Project 2010, Managing Projects. MTAC. Gaúcha. Feeling. Liderança. Agilidade. Follow me!","url":"http://t.co/v7BRmRMPEn","entities":{"url":{"urls":[{"url":"http://t.co/v7BRmRMPEn","expanded_url":"http://mariliabalbe.com","display_url":"mariliabalbe.com","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":2065,"friends_count":1464,"listed_count":81,"created_at":"Thu May 21 15:05:11 +0000 2009","favourites_count":51,"utc_offset":-10800,"time_zone":"Brasilia","geo_enabled":true,"verified":false,"statuses_count":26222,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"9AE4E8","profile_background_image_url":"http://a0.twimg.com/images/themes/theme16/bg.gif","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme16/bg.gif","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/2914714002/d2b0d4771ad8c92841a8d6a37d24c920_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/2914714002/d2b0d4771ad8c92841a8d6a37d24c920_normal.jpeg","profile_link_color":"0084B4","profile_sidebar_border_color":"BDDCAD","profile_sidebar_fill_color":"DDFFCC","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":21,"favorite_count":1,"entities":{"hashtags":[{"text":"PHP","indices":[57,61]},{"text":"Java","indices":[64,69]},{"text":"souDev","indices":[116,123]}],"symbols":[],"urls":[{"url":"http://t.co/Cj6dotO8Be","expanded_url":"http://lnkd.in/zsQhdg","display_url":"lnkd.in/zsQhdg","indices":[90,112]}],"user_mentions":[{"screen_name":"rogerio_gentil","name":"Rogerio J. Gentil","id":71697548,"id_str":"71697548","indices":[21,36]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"pt"},"retweet_count":21,"favorite_count":0,"entities":{"hashtags":[{"text":"PHP","indices":[72,76]},{"text":"Java","indices":[79,84]},{"text":"souDev","indices":[131,138]}],"symbols":[],"urls":[{"url":"http://t.co/Cj6dotO8Be","expanded_url":"http://lnkd.in/zsQhdg","display_url":"lnkd.in/zsQhdg","indices":[105,127]}],"user_mentions":[{"screen_name":"maribalbe","name":"Marília Balbé","id":41602902,"id_str":"41602902","indices":[3,13]},{"screen_name":"rogerio_gentil","name":"Rogerio J. Gentil","id":71697548,"id_str":"71697548","indices":[36,51]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"pt"},{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 19:16:15 +0000 2013","id":360841008411447296,"id_str":"360841008411447296","text":"RT @danielleandy: Finding a way to have our morning coffee together! #bestneighbors #technology #java #screenshot… http://t.co/ZakQ5Ip16C","source":"<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":169605040,"id_str":"169605040","name":"Bucko","screen_name":"jonathonbuckley","location":"Los Angeles","description":"","url":"http://t.co/Vsgepye3eK","entities":{"url":{"urls":[{"url":"http://t.co/Vsgepye3eK","expanded_url":"http://jonathonbuckley.com","display_url":"jonathonbuckley.com","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":2059,"friends_count":116,"listed_count":86,"created_at":"Thu Jul 22 18:56:12 +0000 2010","favourites_count":5,"utc_offset":-25200,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":436,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"1A1B1F","profile_background_image_url":"http://a0.twimg.com/images/themes/theme9/bg.gif","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme9/bg.gif","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/1097180716/8X10_6255_no_pink_small_normal.jpg","profile_image_url_https":"https://si0.twimg.com/profile_images/1097180716/8X10_6255_no_pink_small_normal.jpg","profile_link_color":"2FC2EF","profile_sidebar_border_color":"181A1E","profile_sidebar_fill_color":"252429","profile_text_color":"666666","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"metadata":{"result_type":"recent","iso_language_code":"en"},"created_at":"Fri Jul 26 16:44:25 +0000 2013","id":360802801032499200,"id_str":"360802801032499200","text":"Finding a way to have our morning coffee together! #bestneighbors #technology #java #screenshot… http://t.co/ZakQ5Ip16C","source":"<a href=\"http://instagram.com\" rel=\"nofollow\">Instagram</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":259458041,"id_str":"259458041","name":"Danielle Anderson","screen_name":"danielleandy","location":"Los Angeles ","description":"","url":"http://t.co/JiAcLT2Wfg","entities":{"url":{"urls":[{"url":"http://t.co/JiAcLT2Wfg","expanded_url":"http://www.danielleandy.com","display_url":"danielleandy.com","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":209,"friends_count":127,"listed_count":3,"created_at":"Tue Mar 01 23:31:29 +0000 2011","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":1451,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://a0.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_image_url":"http://a0.twimg.com/profile_images/378800000130553531/82c57daecf779a8d61f17a53a44d31d3_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/378800000130553531/82c57daecf779a8d61f17a53a44d31d3_normal.jpeg","profile_banner_url":"https://pbs.twimg.com/profile_banners/259458041/1373653784","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":1,"favorite_count":0,"entities":{"hashtags":[{"text":"bestneighbors","indices":[51,65]},{"text":"technology","indices":[66,77]},{"text":"java","indices":[79,84]},{"text":"screenshot","indices":[85,96]}],"symbols":[],"urls":[{"url":"http://t.co/ZakQ5Ip16C","expanded_url":"http://instagram.com/p/cPHow7KIcS/","display_url":"instagram.com/p/cPHow7KIcS/","indices":[98,120]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},"retweet_count":1,"favorite_count":0,"entities":{"hashtags":[{"text":"bestneighbors","indices":[69,83]},{"text":"technology","indices":[84,95]},{"text":"java","indices":[97,102]},{"text":"screenshot","indices":[103,114]}],"symbols":[],"urls":[{"url":"http://t.co/ZakQ5Ip16C","expanded_url":"http://instagram.com/p/cPHow7KIcS/","display_url":"instagram.com/p/cPHow7KIcS/","indices":[116,138]}],"user_mentions":[{"screen_name":"danielleandy","name":"Danielle Anderson","id":259458041,"id_str":"259458041","indices":[3,16]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"en"},{"metadata":{"result_type":"recent","iso_language_code":"in"},"created_at":"Fri Jul 26 19:11:01 +0000 2013","id":360839690812784641,"id_str":"360839690812784641","text":"Rip-off or investor's dream? You decide...http://t.co/yLzRPs1Qly #Bandar #Lampung #java #Sumatra #Banten #Riau #Padang //","source":"<a href=\"http://www.hootsuite.com\" rel=\"nofollow\">HootSuite</a>","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":854562582,"id_str":"854562582","name":"SKS Media Londres","screen_name":"SKSMediaLondres","location":"","description":"Nous sommes aussi #teamfollowback #followback @sksfollowback","url":"http://t.co/g6dzOOabDQ","entities":{"url":{"urls":[{"url":"http://t.co/g6dzOOabDQ","expanded_url":"http://www.niche-advertising.co.uk","display_url":"niche-advertising.co.uk","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":1972,"friends_count":1380,"listed_count":100,"created_at":"Sun Sep 30 11:39:09 +0000 2012","favourites_count":439,"utc_offset":7200,"time_zone":"Amsterdam","geo_enabled":false,"verified":false,"statuses_count":144790,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http://a0.twimg.com/profile_background_images/673161806/9c3894fdf100336e2f53e97bffeace6c.jpeg","profile_background_image_url_https":"https://si0.twimg.com/profile_background_images/673161806/9c3894fdf100336e2f53e97bffeace6c.jpeg","profile_background_tile":true,"profile_image_url":"http://a0.twimg.com/profile_images/2665504502/86c0fc8adfb2d7f13e687f7dbfddf876_normal.jpeg","profile_image_url_https":"https://si0.twimg.com/profile_images/2665504502/86c0fc8adfb2d7f13e687f7dbfddf876_normal.jpeg","profile_link_color":"0084B4","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[{"text":"Bandar","indices":[65,72]},{"text":"Lampung","indices":[73,81]},{"text":"java","indices":[82,87]},{"text":"Sumatra","indices":[88,96]},{"text":"Banten","indices":[97,104]},{"text":"Riau","indices":[105,110]},{"text":"Padang","indices":[111,118]}],"symbols":[],"urls":[{"url":"http://t.co/yLzRPs1Qly","expanded_url":"http://tinyurl.com/dxxrao5","display_url":"tinyurl.com/dxxrao5","indices":[42,64]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"lang":"in"}],"search_metadata":{"completed_in":0.033,"max_id":360844831439855616,"max_id_str":"360844831439855616","next_results":"?max_id=360839690812784640&q=%23java&include_entities=1","query":"%23java","refresh_url":"?since_id=360844831439855616&q=%23java&include_entities=1","count":15,"since_id":0,"since_id_str":"0"}} +
diff --git a/impl/src/test/resources/wiki.json b/impl/src/test/resources/wiki.json new file mode 100644 index 0000000..17bb193 --- /dev/null +++ b/impl/src/test/resources/wiki.json
@@ -0,0 +1,21 @@ +{ + "firstName": "John", + "lastName": "Smith", + "age": 25, + "address": { + "streetAddress": "21 2nd Street", + "city": "New York", + "state": "NY", + "postalCode": "10021" + }, + "phoneNumber": [ + { + "type": "home", + "number": "212 555-1234" + }, + { + "type": "fax", + "number": "646 555-4567" + } + ] +}
diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml new file mode 100644 index 0000000..1f2222b --- /dev/null +++ b/jaxrs/pom.xml
@@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish</groupId> + <artifactId>json</artifactId> + <version>2.0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <groupId>org.glassfish</groupId> + <artifactId>jsonp-jaxrs</artifactId> + <packaging>jar</packaging> + <version>2.0.1</version> + <name>Jakarta JSON Processing Media for Jakarta RESTful Web Services</name> + <description>Jakarta RESTful Web Services MessageBodyReader and MessageBodyWriter to support JsonValue API of Jakarta JSON Processing</description> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>jakarta.ws.rs</groupId> + <artifactId>jakarta.ws.rs-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>jakarta.xml.bind</groupId> + <artifactId>jakarta.xml.bind-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>jakarta.annotation</groupId> + <artifactId>jakarta.annotation-api</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <executions> + <execution> + <id>bundle-manifest</id> + <phase>process-classes</phase> + <goals> + <goal>manifest</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile> + </archive> + </configuration> + </plugin> + </plugins> + </build> + +</project>
diff --git a/jaxrs/src/main/java/module-info.java b/jaxrs/src/main/java/module-info.java new file mode 100644 index 0000000..79fbbc8 --- /dev/null +++ b/jaxrs/src/main/java/module-info.java
@@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +module org.glassfish.json.jaxrs { + + requires jakarta.json; + requires jakarta.annotation; + requires jakarta.ws.rs; + + exports org.glassfish.json.jaxrs; + +}
diff --git a/jaxrs/src/main/java/org/glassfish/json/jaxrs/JsonValueBodyReader.java b/jaxrs/src/main/java/org/glassfish/json/jaxrs/JsonValueBodyReader.java new file mode 100644 index 0000000..939982d --- /dev/null +++ b/jaxrs/src/main/java/org/glassfish/json/jaxrs/JsonValueBodyReader.java
@@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.jaxrs; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import jakarta.json.Json; +import jakarta.json.JsonReader; +import jakarta.json.JsonReaderFactory; +import jakarta.json.JsonValue; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.ext.MessageBodyReader; +import jakarta.ws.rs.ext.Provider; + +/** + * Jakarta RESTful Web Services MessageBodyReader for JsonValue. + * This allows JsonValue to be a parameter of a resource method. + * + * @author Jitendra Kotamraju + * @author Blaise Doughan + * @author Michal Gajdos + */ +@Provider +@Consumes({"application/json", "text/json", "*/*"}) +public class JsonValueBodyReader implements MessageBodyReader<JsonValue> { + private final JsonReaderFactory rf = Json.createReaderFactory(null); + + private static final String JSON = "json"; + private static final String PLUS_JSON = "+json"; + + @Override + public boolean isReadable(Class<?> aClass, Type type, + Annotation[] annotations, MediaType mediaType) { + return JsonValue.class.isAssignableFrom(aClass) && supportsMediaType(mediaType); + } + + /** + * @return true for all media types of the pattern */json and + * */*+json. + */ + private static boolean supportsMediaType(final MediaType mediaType) { + return mediaType.getSubtype().equals(JSON) || mediaType.getSubtype().endsWith(PLUS_JSON); + } + + @Override + public JsonValue readFrom(Class<JsonValue> jsonValueClass, + Type type, Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, String> stringStringMultivaluedMap, + InputStream inputStream) throws IOException, WebApplicationException { + try (JsonReader reader = rf.createReader(inputStream)) { + return reader.readValue(); + } + } +}
diff --git a/jaxrs/src/main/java/org/glassfish/json/jaxrs/JsonValueBodyWriter.java b/jaxrs/src/main/java/org/glassfish/json/jaxrs/JsonValueBodyWriter.java new file mode 100644 index 0000000..35f2729 --- /dev/null +++ b/jaxrs/src/main/java/org/glassfish/json/jaxrs/JsonValueBodyWriter.java
@@ -0,0 +1,98 @@ +/* + * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.json.jaxrs; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; +import jakarta.annotation.PostConstruct; +import jakarta.json.Json; +import jakarta.json.JsonValue; +import jakarta.json.JsonWriter; +import jakarta.json.JsonWriterFactory; +import jakarta.json.stream.JsonGenerator; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.Configuration; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.ext.MessageBodyWriter; +import jakarta.ws.rs.ext.Provider; + +/** + * Jakarta RESTful Web Services MessageBodyWriter for JsonValue. + * This allows JsonValue to be return type of a resource method. + * + * @author Jitendra Kotamraju + * @author Blaise Doughan + * @author Michal Gajdos + */ +@Provider +@Produces({"application/json", "text/json", "*/*"}) +public class JsonValueBodyWriter implements MessageBodyWriter<JsonValue> { + private static final String JSON = "json"; + private static final String PLUS_JSON = "+json"; + + private JsonWriterFactory wf = Json.createWriterFactory(null); + + @Context + private Configuration config; + + @PostConstruct + private void init() { + Map<String, Object> props = new HashMap<>(); + if (config != null && config.getProperties().containsKey(JsonGenerator.PRETTY_PRINTING)) { + props.put(JsonGenerator.PRETTY_PRINTING, true); + } + wf = Json.createWriterFactory(props); + } + + @Override + public boolean isWriteable(Class<?> aClass, + Type type, Annotation[] annotations, MediaType mediaType) { + return JsonValue.class.isAssignableFrom(aClass) && supportsMediaType(mediaType); + } + + /** + * @return true for all media types of the pattern */json and + * */*+json. + */ + private static boolean supportsMediaType(final MediaType mediaType) { + return mediaType.getSubtype().equals(JSON) || mediaType.getSubtype().endsWith(PLUS_JSON); + } + + @Override + public long getSize(JsonValue jsonValue, Class<?> aClass, + Type type, Annotation[] annotations, MediaType mediaType) { + + return -1; + } + + @Override + public void writeTo(JsonValue jsonValue, Class<?> aClass, Type type, + Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, Object> stringObjectMultivaluedMap, + OutputStream outputStream) throws IOException, WebApplicationException { + try (JsonWriter writer = wf.createWriter(outputStream)) { + writer.write(jsonValue); + } + } +}
diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..f22b709 --- /dev/null +++ b/pom.xml
@@ -0,0 +1,464 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.ee4j</groupId> + <artifactId>project</artifactId> + <version>1.0.6</version> + </parent> + + <groupId>org.glassfish</groupId> + <artifactId>json</artifactId> + <packaging>pom</packaging> + <version>2.0.1</version> + <name>Jakarta JSON Processing</name> + <description>Jakarta JSON Processing defines a Java(R) based framework for parsing, generating, transforming, and querying JSON documents.</description> + <url>https://github.com/eclipse-ee4j/jsonp</url> + + <scm> + <connection>scm:git:git://github.com/eclipse-ee4j/jsonp.git</connection> + <developerConnection>scm:git:git@github.com:eclipse-ee4j/jsonp.git</developerConnection> + <url>https://github.com/eclipse-ee4j/jsonp</url> + <tag>HEAD</tag> + </scm> + + <licenses> + <license> + <name>Eclipse Public License 2.0</name> + <url>https://projects.eclipse.org/license/epl-2.0</url> + <distribution>repo</distribution> + </license> + <license> + <name>GNU General Public License, version 2 with the GNU Classpath Exception</name> + <url>https://projects.eclipse.org/license/secondary-gpl-2.0-cp</url> + <distribution>repo</distribution> + </license> + </licenses> + + <developers> + <developer> + <id>m0mus</id> + <name>Dmitry Kornilov</name> + <organization>Oracle</organization> + <roles> + <role>project lead</role> + </roles> + </developer> + <developer> + <id>lukasj</id> + <name>Lukas Jungmann</name> + <organization>Oracle</organization> + <roles> + <role>dev lead</role> + </roles> + </developer> + </developers> + + <properties> + <api_package>jakarta.json</api_package> + <impl_namespace>org.glassfish</impl_namespace> + <spec_version>2.0</spec_version> + <new_spec_version>2.1</new_spec_version> + <new_spec_impl_version>2.1.0</new_spec_impl_version> + <impl_version>${project.version}</impl_version> + <new_impl_version>2.1.0</new_impl_version> + <non.final>false</non.final> + <legal.doc.source>${maven.multiModuleProjectDirectory}</legal.doc.source> + <config.dir>${project.root.location}/etc/config</config.dir> + <copyright.exclude>${config.dir}/copyright-exclude</copyright.exclude> + <copyright.templatefile>${config.dir}/copyright.txt</copyright.templatefile> + <copyright.ignoreyear>false</copyright.ignoreyear> + <copyright.scmonly>true</copyright.scmonly> + <copyright.update>false</copyright.update> + <spotbugs.exclude>${config.dir}/exclude.xml</spotbugs.exclude> + <spotbugs.skip>false</spotbugs.skip> + <spotbugs.threshold>Low</spotbugs.threshold> + <spotbugs.version>4.2.2</spotbugs.version> + + <jakarta.json-api.version>2.0.1</jakarta.json-api.version> + + <jakarta.annotation-api.version>2.0.0</jakarta.annotation-api.version> + <jakarta.xml.bind-api.version>3.0.1</jakarta.xml.bind-api.version> + <jakarta.ws.rs-api.version>3.0.0</jakarta.ws.rs-api.version> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <executions> + <execution> + <id>enforce-maven</id> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireJavaVersion> + <version>[11,)</version> + </requireJavaVersion> + <requireMavenVersion> + <version>[3.6.0,)</version> + </requireMavenVersion> + </rules> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.commonjava.maven.plugins</groupId> + <artifactId>directory-maven-plugin</artifactId> + <executions> + <execution> + <id>find-project-root</id> + <phase>validate</phase> + <goals> + <goal>highest-basedir</goal> + </goals> + <configuration> + <property>project.root.location</property> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <release>9</release> + <compilerArgs> + <arg>-Xlint:all</arg> + </compilerArgs> + </configuration> + <executions> + <execution> + <id>base-compile</id> + <goals> + <goal>compile</goal> + </goals> + <configuration> + <release>8</release> + <excludes> + <exclude>module-info.java</exclude> + </excludes> + </configuration> + </execution> + </executions> + </plugin> + <!-- Requires validate target to initialize copyright.config.dir properly --> + <!-- e.g. mvn validate glassfish-copyright:repair --> + <plugin> + <groupId>org.glassfish.copyright</groupId> + <artifactId>glassfish-copyright-maven-plugin</artifactId> + <configuration> + <templateFile>${copyright.templatefile}</templateFile> + <excludeFile>${copyright.exclude}</excludeFile> + <!-- skip files not under SCM--> + <scmOnly>${copyright.scmonly}</scmOnly> + <!-- for use with repair --> + <update>${copyright.update}</update> + <!-- check that year is correct --> + <ignoreYear>${copyright.ignoreyear}</ignoreYear> + <quiet>false</quiet> + </configuration> + <executions> + <execution> + <goals> + <goal>check</goal> + </goals> + <phase>verify</phase> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>add-legal-resource</id> + <phase>generate-resources</phase> + <goals> + <goal>add-resource</goal> + </goals> + <configuration> + <resources> + <resource> + <directory>${legal.doc.source}</directory> + <includes> + <include>NOTICE.md</include> + <include>LICENSE.md</include> + </includes> + <targetPath>META-INF</targetPath> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addDefaultEntries>false</addDefaultEntries> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + </manifest> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-release-plugin</artifactId> + <configuration> + <mavenExecutorId>forked-path</mavenExecutorId> + <useReleaseProfile>false</useReleaseProfile> + <arguments>${release.arguments}</arguments> + </configuration> + </plugin> + </plugins> + + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <version>3.0.0-M3</version> + </plugin> + <plugin> + <groupId>org.commonjava.maven.plugins</groupId> + <artifactId>directory-maven-plugin</artifactId> + <version>0.3.1</version> + </plugin> + <plugin> + <groupId>com.github.spotbugs</groupId> + <artifactId>spotbugs-maven-plugin</artifactId> + <version>${spotbugs.version}</version> + </plugin> + <plugin> + <groupId>org.glassfish.build</groupId> + <artifactId>spec-version-maven-plugin</artifactId> + <version>2.1</version> + </plugin> + <plugin> + <groupId>org.glassfish.copyright</groupId> + <artifactId>glassfish-copyright-maven-plugin</artifactId> + <version>2.4</version> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>5.1.1</version> + <configuration> + <instructions> + <_noextraheaders>true</_noextraheaders> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>3.2.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>3.2.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.2.1</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.2.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>3.1.2</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <version>3.2.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-clean-plugin</artifactId> + <version>3.1.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + <version>3.9.1</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.0.0-M5</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <version>3.3.0</version> + </plugin> + </plugins> + </pluginManagement> + </build> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>jakarta.ws.rs</groupId> + <artifactId>jakarta.ws.rs-api</artifactId> + <version>${jakarta.ws.rs-api.version}</version> + </dependency> + <dependency> + <groupId>jakarta.annotation</groupId> + <artifactId>jakarta.annotation-api</artifactId> + <version>${jakarta.annotation-api.version}</version> + </dependency> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <version>${jakarta.json-api.version}</version> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jakarta.json</artifactId> + <classifier>module</classifier> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>jsonp-jaxrs</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>jakarta.xml.bind</groupId> + <artifactId>jakarta.xml.bind-api</artifactId> + <version>${jakarta.xml.bind-api.version}</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13.2</version> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-core</artifactId> + <version>1.3</version> + <scope>test</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <modules> + <module>impl</module> + <module>jaxrs</module> + <module>bundles</module> + </modules> + + <profiles> + <profile> + <id>all</id> + <dependencyManagement> + <!-- dependencies used by demo projects only --> + <dependencies> + <dependency> + <groupId>jakarta.servlet</groupId> + <artifactId>jakarta.servlet-api</artifactId> + <version>5.0.0</version> + </dependency> + <dependency> + <groupId>com.sun.xml.bind</groupId> + <artifactId>jaxb-impl</artifactId> + <version>3.0.0</version> + </dependency> + </dependencies> + </dependencyManagement> + + <modules> + <module>gf</module> + <module>demos</module> + </modules> + + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <version>3.3.1</version> + <configuration> + <failOnMissingWebXml>false</failOnMissingWebXml> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>wagon-maven-plugin</artifactId> + <version>2.0.2</version> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>3.0.0</version> + </plugin> + </plugins> + </pluginManagement> + </build> + </profile> + </profiles> + + <reporting> + <plugins> + <plugin> + <groupId>com.github.spotbugs</groupId> + <artifactId>spotbugs-maven-plugin</artifactId> + <configuration> + <skip>${spotbugs.skip}</skip> + <threshold>${spotbugs.threshold}</threshold> + <findbugsXmlWithMessages>true</findbugsXmlWithMessages> + <excludeFilterFile> + ${spotbugs.exclude} + </excludeFilterFile> + <fork>true</fork> + </configuration> + </plugin> + </plugins> + </reporting> + +</project>
diff --git a/spec/.gitignore b/spec/.gitignore new file mode 100644 index 0000000..450b4b3 --- /dev/null +++ b/spec/.gitignore
@@ -0,0 +1,2 @@ +.m2/ +target/
diff --git a/spec/LICENSE b/spec/LICENSE new file mode 100644 index 0000000..d3087e4 --- /dev/null +++ b/spec/LICENSE
@@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership.
diff --git a/spec/README.md b/spec/README.md new file mode 100644 index 0000000..e25307a --- /dev/null +++ b/spec/README.md
@@ -0,0 +1,26 @@ +Jakarta JSON Processing Specification +====================================== + +This project generates the Jakarta JSON Processing Specification. + +Building +-------- + +Prerequisites: + +* JDK8+ +* Maven 3.0.3+ + +Run the full build with DRAFT status: + +`mvn install` + +Run the full build with custom status (ex. "Final Release"): + +`mvn install -Dstatus=“Final Release”` + +Locate the html files: +- `target/generated-docs/jsonp-spec-<version>.html` + +Locate the PDF files: +- `target/generated-docs/jsonp-spec-<version>.pdf`
diff --git a/spec/pom.xml b/spec/pom.xml new file mode 100644 index 0000000..be9a379 --- /dev/null +++ b/spec/pom.xml
@@ -0,0 +1,198 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <groupId>org.eclipse.ee4j</groupId> + <artifactId>project</artifactId> + <version>1.0.6</version> + <relativePath/> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-spec</artifactId> + <packaging>pom</packaging> + <version>2.0-SNAPSHOT</version> + <name>Jakarta JSON Processing Specification</name> + + <properties> + <site.output.dir>${project.build.directory}/staging</site.output.dir> + <maven.site.skip>true</maven.site.skip> + <asciidoctor.maven.plugin.version>2.0.0</asciidoctor.maven.plugin.version> + <asciidoctorj.pdf.version>1.5.3</asciidoctorj.pdf.version> + <!-- status: DRAFT, BETA, etc., or blank for final --> + <status>DRAFT</status> + <maven.build.timestamp.format>MMMM dd, yyyy</maven.build.timestamp.format> + <revisiondate>${maven.build.timestamp}</revisiondate> + </properties> + + <scm> + <connection>scm:git:git@github.com:eclipse-ee4j/jsonp.git</connection> + <developerConnection>scm:git:git@github.com:eclipse-ee4j/jsonp.git</developerConnection> + <url>https://github.com/eclipse-ee4j/jsonp</url> + <tag>HEAD</tag> + </scm> + + <distributionManagement> + <site> + <url>scm:git:git@github.com:eclipse-ee4j/jsonp.git</url> + </site> + </distributionManagement> + + <build> + <defaultGoal>package</defaultGoal> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <version>1.4.1</version> + <executions> + <execution> + <id>enforce-versions</id> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireJavaVersion> + <version>[1.8.0,)</version> + <message>You need JDK8 or higher</message> + </requireJavaVersion> + </rules> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.asciidoctor</groupId> + <artifactId>asciidoctor-maven-plugin</artifactId> + <version>${asciidoctor.maven.plugin.version}</version> + <dependencies> + <dependency> + <groupId>org.asciidoctor</groupId> + <artifactId>asciidoctorj-pdf</artifactId> + <version>${asciidoctorj.pdf.version}</version> + </dependency> + </dependencies> + <executions> + <execution> + <id>asciidoc-to-html</id> + <phase>generate-resources</phase> + <goals> + <goal>process-asciidoc</goal> + </goals> + <configuration> + <backend>html5</backend> + <outputFile>${project.build.directory}/generated-docs/jsonp-spec-${project.version}.html</outputFile> + <attributes> + <doctype>book</doctype> + <status>${status}</status> + <data-uri /> + <icons>font</icons> + <toc>left</toc> + <icons>font</icons> + <sectanchors>true</sectanchors> + <idprefix /> + <idseparator>-</idseparator> + <docinfo1>true</docinfo1> + </attributes> + </configuration> + </execution> + <execution> + <id>asciidoc-to-pdf</id> + <phase>generate-resources</phase> + <goals> + <goal>process-asciidoc</goal> + </goals> + <configuration> + <backend>pdf</backend> + <outputFile>${project.build.directory}/generated-docs/jsonp-spec-${project.version}.pdf</outputFile> + <attributes> + <pdf-stylesdir>${project.basedir}/src/theme</pdf-stylesdir> + <pdf-style>jakartaee</pdf-style> + <doctype>book</doctype> + <status>${status}</status> + <data-uri /> + <icons>font</icons> + <pagenums /> + <toc /> + <icons>font</icons> + <sectanchors>true</sectanchors> + <idprefix /> + <idseparator>-</idseparator> + <docinfo1>true</docinfo1> + <embedAssets>true</embedAssets> + </attributes> + </configuration> + </execution> + </executions> + <configuration> + <sourceDocumentName>jsonp-spec.adoc</sourceDocumentName> + <sourceHighlighter>coderay</sourceHighlighter> + <attributes> + <revnumber>${project.version}</revnumber> + <revremark>${status}</revremark> + <revdate>${revisiondate}</revdate> + </attributes> + </configuration> + + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-release-plugin</artifactId> + <version>2.5.2</version> + <configuration> + <mavenExecutorId>forked-path</mavenExecutorId> + <useReleaseProfile>false</useReleaseProfile> + <arguments>${release.arguments}</arguments> + </configuration> + <dependencies> + <dependency> + <groupId>org.apache.maven.scm</groupId> + <artifactId>maven-scm-provider-gitexe</artifactId> + <version>1.9.4</version> + </dependency> + </dependencies> + </plugin> + + <!-- + This is the rule that builds the zip file for download. + --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <version>3.3.0</version> + <inherited>false</inherited> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <appendAssemblyId>false</appendAssemblyId> + <descriptors> + <descriptor>${project.basedir}/src/assembly/assembly.xml</descriptor> + </descriptors> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project>
diff --git a/spec/src/assembly/assembly.xml b/spec/src/assembly/assembly.xml new file mode 100644 index 0000000..53f9453 --- /dev/null +++ b/spec/src/assembly/assembly.xml
@@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- + + Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<assembly> + <id>spec</id> + <formats> + <format>zip</format> + </formats> + <baseDirectory>jsonp-spec</baseDirectory> + <fileSets> + <fileSet> + <directory>target/generated-docs</directory> + <outputDirectory></outputDirectory> + </fileSet> + </fileSets> +</assembly>
diff --git a/spec/src/main/asciidoc/images/jakarta_ee_logo_schooner_color_stacked_default.png b/spec/src/main/asciidoc/images/jakarta_ee_logo_schooner_color_stacked_default.png new file mode 100644 index 0000000..97b46ce --- /dev/null +++ b/spec/src/main/asciidoc/images/jakarta_ee_logo_schooner_color_stacked_default.png Binary files differ
diff --git a/spec/src/main/asciidoc/jsonp-spec.adoc b/spec/src/main/asciidoc/jsonp-spec.adoc new file mode 100644 index 0000000..5077a92 --- /dev/null +++ b/spec/src/main/asciidoc/jsonp-spec.adoc
@@ -0,0 +1,28 @@ +// +// Copyright (c) 2017, 2020 Contributors to the Eclipse Foundation +// + += Jakarta JSON Processing +:authors: Jakarta JSON Processing Team, https://projects.eclipse.org/projects/ee4j.jsonp +:email: https://dev.eclipse.org/mailman/listinfo/jsonp-dev +:version-label!: +:doctype: book +:license: Eclipse Foundation Specification License v1.0 +:source-highlighter: coderay +:toc: left +:toclevels: 4 +:sectnumlevels: 4 +:sectanchors: +ifdef::backend-pdf[] +:pagenums: +:numbered: +:title-logo-image: image:images/jakarta_ee_logo_schooner_color_stacked_default.png[pdfwidth=4.25in,align=right] +endif::[] + +// == License +:sectnums!: +include::license-efsl.adoc[] + +// == Spec +:sectnums: +include::jsonp.adoc[]
diff --git a/spec/src/main/asciidoc/jsonp.adoc b/spec/src/main/asciidoc/jsonp.adoc new file mode 100644 index 0000000..e33e8ff --- /dev/null +++ b/spec/src/main/asciidoc/jsonp.adoc
@@ -0,0 +1,7 @@ +// +// Copyright (c) 2018, 2020 Contributors to the Eclipse Foundation +// + +== Introduction + +Jakarta JSON Processing defines a Java(R) based framework for parsing, generating, transforming, and querying JSON documents.
diff --git a/spec/src/main/asciidoc/license-efsl.adoc b/spec/src/main/asciidoc/license-efsl.adoc new file mode 100644 index 0000000..d900a4a --- /dev/null +++ b/spec/src/main/asciidoc/license-efsl.adoc
@@ -0,0 +1,79 @@ +[subs="normal"] +.... +Specification: {doctitle} + +Version: {revnumber} + +ifeval::["{revremark}" != ""] +Status: {revremark} +endif::[] +ifeval::["{revremark}" == ""] +Status: Final Release +endif::[] + +Release: {revdate} +.... + +Copyright (c) 2019 Eclipse Foundation. + +=== Eclipse Foundation Specification License + +By using and/or copying this document, or the Eclipse Foundation +document from which this statement is linked, you (the licensee) agree +that you have read, understood, and will comply with the following +terms and conditions: + +Permission to copy, and distribute the contents of this document, or +the Eclipse Foundation document from which this statement is linked, in +any medium for any purpose and without fee or royalty is hereby +granted, provided that you include the following on ALL copies of the +document, or portions thereof, that you use: + +* link or URL to the original Eclipse Foundation document. +* All existing copyright notices, or if one does not exist, a notice + (hypertext is preferred, but a textual representation is permitted) + of the form: "Copyright (c) [$date-of-document] + Eclipse Foundation, Inc. <<url to this license>>" + +Inclusion of the full text of this NOTICE must be provided. We +request that authorship attribution be provided in any software, +documents, or other items or products that you create pursuant to the +implementation of the contents of this document, or any portion +thereof. + +No right to create modifications or derivatives of Eclipse Foundation +documents is granted pursuant to this license, except anyone may +prepare and distribute derivative works and portions of this document +in software that implements the specification, in supporting materials +accompanying such software, and in documentation of such software, +PROVIDED that all such works include the notice below. HOWEVER, the +publication of derivative works of this document for use as a technical +specification is expressly prohibited. + +The notice is: + +"Copyright (c) 2018 Eclipse Foundation. This software or +document includes material copied from or derived from [title and URI +of the Eclipse Foundation specification document]." + +==== Disclaimers + +THIS DOCUMENT IS PROVIDED "AS IS," AND THE COPYRIGHT +HOLDERS AND THE ECLIPSE FOUNDATION MAKE NO REPRESENTATIONS OR +WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, +NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE +SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS +WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR +OTHER RIGHTS. + +THE COPYRIGHT HOLDERS AND THE ECLIPSE FOUNDATION WILL NOT BE LIABLE +FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT +OF ANY USE OF THE DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE +CONTENTS THEREOF. + +The name and trademarks of the copyright holders or the Eclipse +Foundation may NOT be used in advertising or publicity pertaining to +this document or its contents without specific, written prior +permission. Title to copyright in this document will at all times +remain with copyright holders. \ No newline at end of file
diff --git a/spec/src/theme/jakartaee-theme.yml b/spec/src/theme/jakartaee-theme.yml new file mode 100644 index 0000000..6092a2f --- /dev/null +++ b/spec/src/theme/jakartaee-theme.yml
@@ -0,0 +1,299 @@ +# +# Following is the asciidoctor-pdf default theme [1], with small +# customizations, mostly for header and footer, marked "EE". +# +# [1] https://github.com/asciidoctor/asciidoctor-pdf/blob/master/data/themes/default-theme.yml +# +font: + catalog: + # Noto Serif supports Latin, Latin-1 Supplement, Latin Extended-A, Greek, Cyrillic, Vietnamese & an assortment of symbols + Noto Serif: + normal: notoserif-regular-subset.ttf + bold: notoserif-bold-subset.ttf + italic: notoserif-italic-subset.ttf + bold_italic: notoserif-bold_italic-subset.ttf + # M+ 1mn supports ASCII and the circled numbers used for conums + M+ 1mn: + normal: mplus1mn-regular-ascii-conums.ttf + bold: mplus1mn-bold-ascii.ttf + italic: mplus1mn-italic-ascii.ttf + bold_italic: mplus1mn-bold_italic-ascii.ttf + # M+ 1p supports Latin, Latin-1 Supplement, Latin Extended, Greek, Cyrillic, Vietnamese, Japanese & an assortment of symbols + # It also provides arrows for ->, <-, => and <= replacements in case these glyphs are missing from font + M+ 1p Fallback: + normal: mplus1p-regular-fallback.ttf + bold: mplus1p-regular-fallback.ttf + italic: mplus1p-regular-fallback.ttf + bold_italic: mplus1p-regular-fallback.ttf + fallbacks: + - M+ 1p Fallback +page: + background_color: ffffff + layout: portrait + margin: [0.5in, 0.67in, 0.67in, 0.67in] + # margin_inner and margin_outer keys are used for recto/verso print margins when media=prepress + margin_inner: 0.75in + margin_outer: 0.59in + #size: A4 # EE + size: Letter # EE +base: + align: justify + # color as hex string (leading # is optional) + font_color: 333333 + # color as RGB array + #font_color: [51, 51, 51] + # color as CMYK array (approximated) + #font_color: [0, 0, 0, 0.92] + #font_color: [0, 0, 0, 92%] + font_family: Noto Serif + # choose one of these font_size/line_height_length combinations + #font_size: 14 + #line_height_length: 20 + #font_size: 11.25 + #line_height_length: 18 + #font_size: 11.2 + #line_height_length: 16 + font_size: 10.5 + #line_height_length: 15 + # correct line height for Noto Serif metrics + line_height_length: 12 + #font_size: 11.25 + #line_height_length: 18 + line_height: $base_line_height_length / $base_font_size + font_size_large: round($base_font_size * 1.25) + font_size_small: round($base_font_size * 0.85) + font_size_min: $base_font_size * 0.75 + font_style: normal + border_color: eeeeee + border_radius: 4 + border_width: 0.5 +# FIXME vertical_rhythm is weird; we should think in terms of ems +#vertical_rhythm: $base_line_height_length * 2 / 3 +# correct line height for Noto Serif metrics (comes with built-in line height) +vertical_rhythm: $base_line_height_length +horizontal_rhythm: $base_line_height_length +# QUESTION should vertical_spacing be block_spacing instead? +vertical_spacing: $vertical_rhythm +link: + font_color: 428bca +# literal is currently used for inline monospaced in prose and table cells +literal: + font_color: b12146 + font_family: M+ 1mn +menu_caret_content: " <font size=\"1.15em\"><color rgb=\"b12146\">\u203a</color></font> " +heading: + align: left + #font_color: 181818 + font_color: $base_font_color + font_family: $base_font_family + font_style: bold + # h1 is used for part titles (book doctype) or the doctitle (article doctype) + #h1_font_size: floor($base_font_size * 2.6) # EE + h1_font_size: floor($base_font_size * 2.5) # EE, squeeze title onto one line + # h2 is used for chapter titles (book doctype only) + h2_font_size: floor($base_font_size * 2.15) + h3_font_size: round($base_font_size * 1.7) + h4_font_size: $base_font_size_large + h5_font_size: $base_font_size + h6_font_size: $base_font_size_small + #line_height: 1.4 + # correct line height for Noto Serif metrics (comes with built-in line height) + line_height: 1 + margin_top: $vertical_rhythm * 0.4 + margin_bottom: $vertical_rhythm * 0.9 +title_page: + align: right + logo: + top: 10% + title: + top: 55% + font_size: $heading_h1_font_size + font_color: 999999 + line_height: 0.9 + subtitle: + font_size: $heading_h3_font_size + font_style: bold_italic + line_height: 1 + authors: + margin_top: $base_font_size * 1.25 + font_size: $base_font_size_large + font_color: 181818 + revision: + margin_top: $base_font_size * 1.25 +block: + margin_top: 0 + margin_bottom: $vertical_rhythm +caption: + align: left + font_size: $base_font_size * 0.95 + font_style: italic + # FIXME perhaps set line_height instead of / in addition to margins? + margin_inside: $vertical_rhythm / 3 + #margin_inside: $vertical_rhythm / 4 + margin_outside: 0 +lead: + font_size: $base_font_size_large + line_height: 1.4 +abstract: + font_color: 5c6266 + font_size: $lead_font_size + line_height: $lead_line_height + font_style: italic + first_line_font_style: bold + title: + align: center + font_color: $heading_font_color + font_family: $heading_font_family + font_size: $heading_h4_font_size + font_style: $heading_font_style +admonition: + column_rule_color: $base_border_color + column_rule_width: $base_border_width + padding: [0, $horizontal_rhythm, 0, $horizontal_rhythm] + #icon: + # tip: + # name: fa-lightbulb-o + # stroke_color: 111111 + # size: 24 + label: + text_transform: uppercase + font_style: bold +blockquote: + font_color: $base_font_color + font_size: $base_font_size_large + border_color: $base_border_color + border_width: 5 + # FIXME disable negative padding bottom once margin collapsing is implemented + padding: [0, $horizontal_rhythm, $block_margin_bottom * -0.75, $horizontal_rhythm + $blockquote_border_width / 2] + cite_font_size: $base_font_size_small + cite_font_color: 999999 +# code is used for source blocks (perhaps change to source or listing?) +code: + font_color: $base_font_color + font_family: $literal_font_family + font_size: ceil($base_font_size) + padding: $code_font_size + line_height: 1.25 + # line_gap is an experimental property to control how a background color is applied to an inline block element + line_gap: 3.8 + background_color: f5f5f5 + border_color: cccccc + border_radius: $base_border_radius + border_width: 0.75 +conum: + font_family: M+ 1mn + font_color: $literal_font_color + font_size: $base_font_size + line_height: 4 / 3 +example: + border_color: $base_border_color + border_radius: $base_border_radius + border_width: 0.75 + background_color: ffffff + # FIXME reenable padding bottom once margin collapsing is implemented + padding: [$vertical_rhythm, $horizontal_rhythm, 0, $horizontal_rhythm] +image: + align: left +prose: + margin_top: $block_margin_top + margin_bottom: $block_margin_bottom +sidebar: + background_color: eeeeee + border_color: e1e1e1 + border_radius: $base_border_radius + border_width: $base_border_width + # FIXME reenable padding bottom once margin collapsing is implemented + padding: [$vertical_rhythm, $vertical_rhythm * 1.25, 0, $vertical_rhythm * 1.25] + title: + align: center + font_color: $heading_font_color + font_family: $heading_font_family + font_size: $heading_h4_font_size + font_style: $heading_font_style +thematic_break: + border_color: $base_border_color + border_style: solid + border_width: $base_border_width + margin_top: $vertical_rhythm * 0.5 + margin_bottom: $vertical_rhythm * 1.5 +description_list: + term_font_style: bold + term_spacing: $vertical_rhythm / 4 + description_indent: $horizontal_rhythm * 1.25 +outline_list: + indent: $horizontal_rhythm * 1.5 + #marker_font_color: 404040 + # NOTE outline_list_item_spacing applies to list items that do not have complex content + item_spacing: $vertical_rhythm / 2 +table: + background_color: $page_background_color + #head_background_color: <hex value> + #head_font_color: $base_font_color + head_font_style: bold + #body_background_color: <hex value> + body_stripe_background_color: f9f9f9 + foot_background_color: f0f0f0 + border_color: dddddd + border_width: $base_border_width + cell_padding: 3 +toc: + indent: $horizontal_rhythm + line_height: 1.4 + dot_leader: + #content: ". " + font_color: a9a9a9 + #levels: 2 3 +# NOTE in addition to footer, header is also supported +footer: + font_size: $base_font_size_small + # NOTE if background_color is set, background and border will span width of page + #border_color: dddddd # EE + #border_width: 0.25 # EE + height: $base_line_height_length * 2.5 + line_height: 1 + padding: [$base_line_height_length / 2, 1, 0, 1] + vertical_align: top + #image_vertical_align: <alignment> or <number> + # additional attributes for content: + # * {page-count} + # * {page-number} + # * {document-title} + # * {document-subtitle} + # * {chapter-title} + # * {section-title} + # * {section-or-chapter-title} + recto: + #columns: "<50% =0% >50%" + right: + #content: '{page-number}' # EE + #content: '{section-or-chapter-title} | {page-number}' + #content: '{document-title} | {page-number}' + content: '{document-title}{nbsp}{nbsp}{nbsp} *{page-number}*' # EE + #center: + # content: '{page-number}' + left: # EE + content: '{status}' # EE + verso: + #columns: $footer_recto_columns + left: + #content: $footer_recto_right_content # EE + #content: '{page-number} | {chapter-title}' + content: '*{page-number}* {nbsp}{nbsp}{nbsp}{document-title}' # EE + #center: + # content: '{page-number}' + right: # EE + content: '{status}' # EE +header: # EE + font_size: $base_font_size_small # EE + border_color: dddddd # EE + border_width: 0.25 # EE + height: $base_line_height_length * 2.5 # EE + line_height: 1 # EE + padding: [$base_line_height_length / 2, 1, 0, 1] # EE + vertical_align: top # EE + recto: # EE + right: # EE + content: '{section-or-chapter-title}' # EE + verso: # EE + left: # EE + content: '{section-or-chapter-title}' # EE
diff --git a/tck/pom.xml b/tck/pom.xml new file mode 100644 index 0000000..dd7e80d --- /dev/null +++ b/tck/pom.xml
@@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.ee4j</groupId> + <artifactId>project</artifactId> + <version>1.0.6</version> + </parent> + + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck</artifactId> + <version>2.0.0-SNAPSHOT</version> + <packaging>pom</packaging> + + <modules> + <module>tck-common</module> + <module>tck-tests</module> + <module>tck-tests-plugability</module> + </modules> + + <name>JSON-P TCK</name> + <description>Jakarta JSON-P TCK</description> + + <licenses> + <license> + <name>Eclipse Public License 2.0</name> + <url>https://projects.eclipse.org/license/epl-2.0</url> + <distribution>repo</distribution> + </license> + <license> + <name>GNU General Public License, version 2 with the GNU Classpath Exception</name> + <url>https://projects.eclipse.org/license/secondary-gpl-2.0-cp</url> + <distribution>repo</distribution> + </license> + </licenses> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.target>1.8</maven.compiler.target> + <maven.compiler.source>1.8</maven.compiler.source> + </properties> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-api</artifactId> + <version>2.0.0-RC1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>jakarta.inject</groupId> + <artifactId>jakarta.inject-api</artifactId> + <version>1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.junit</groupId> + <artifactId>arquillian-junit-container</artifactId> + <version>1.6.0.Final</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + </dependency> + </dependencies> +</project>
diff --git a/tck/tck-common/pom.xml b/tck/tck-common/pom.xml new file mode 100644 index 0000000..50d6c67 --- /dev/null +++ b/tck/tck-common/pom.xml
@@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck</artifactId> + <version>2.0.0-SNAPSHOT</version> + </parent> + + <artifactId>jakarta.json-tck-common</artifactId> + <packaging>jar</packaging> + +</project>
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/JSONP_Data.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/JSONP_Data.java new file mode 100644 index 0000000..e7da0b1 --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/JSONP_Data.java
@@ -0,0 +1,177 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.common; + + +import java.util.*; + +public final class JSONP_Data { + + public static final String unicodeControlCharsEscaped = "\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\u0008\\u0009" + + "\\u000a\\u000b\\u000c\\u000d\\u000e\\u000f" + + "\\u000A\\u000B\\u000C\\u000D\\u000E\\u000F" + + "\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019" + + "\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\\u007f" + + "\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F\\u007F" + + "\\u0080\\u0081\\u0082\\u0083\\u0084\\u0085\\u0086\\u0087\\u0088\\u0089" + + "\\u008a\\u008b\\u008c\\u008d\\u008e\\u008f" + + "\\u008A\\u008B\\u008C\\u008D\\u008E\\u008F" + + "\\u0090\\u0091\\u0092\\u0093\\u0094\\u0095\\u0096\\u0097\\u0098\\u0099" + + "\\u009a\\u009b\\u009c\\u009d\\u009e\\u009f" + + "\\u009A\\u009B\\u009C\\u009D\\u009E\\u009F"; + + // NOTE: For the unicode values u000a and u000d we need to use the Java + // escape for both NL and CR as \n and \r respectively + public static final String unicodeControlCharsNonEscaped = "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009" + + "\n\u000b\u000c\r\u000e\u000f" + "\n\u000B\u000C\r\u000E\u000F" + + "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019" + + "\u001a\u001b\u001c\u001d\u001e\u001f\u007f" + + "\u001A\u001B\u001C\u001D\u001E\u001F\u007F" + + "\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089" + + "\u008a\u008b\u008c\u008d\u008e\u008f" + + "\u008A\u008B\u008C\u008D\u008E\u008F" + + "\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099" + + "\u009a\u009b\u009c\u009d\u009e\u009f" + + "\u009A\u009B\u009C\u009D\u009E\u009F"; + + // Standard backslash escape characters + public static final String escapeCharsAsString = "\"\\/\b\f\n\r\t"; + + public static final String asciiCharacters = "!@#$%^&*()_+|~1234567890-=;',./<>? " + + "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; + + public static final String jsonArrayTestData = "[ \"\", \"string\", 100, true, false, null, {}, { \"name\" : \"value\" }, [], [ \"one\", \"two\" ] ]"; + + public static final String jsonObjectTestData = "{" + + "\"emptyString\" : \"\"," + "\"emptyArray\" : []," + + "\"emptyObject\" : {}," + "\"string\" : \"string\"," + + "\"number\" : 100," + "\"true\" : true," + "\"false\" : false," + + "\"null\" : null," + "\"object\" : { \"name\" : \"value\" }," + + "\"array\" : [ \"one\", \"two\" ]," + "}"; + + public static final String jsonArrayTestData2 = "[" + "\"\"," + "[]," + "{}," + + "\"string\"," + "100," + "true," + "false," + "null," + + "{ \"name\" : \"value\" }," + "[ \"one\", \"two\" ]," + "]"; + + public static final String jsonObjectWithAllTypesOfData = "{" + + "\"emptyString\" : \"\"," + "\"emptyArray\" : []," + + "\"emptyObject\" : {}," + "\"string\" : \"string\"," + + "\"number\" : 100," + "\"true\" : true," + "\"false\" : false," + + "\"null\" : null," + "\"object\" : {" + "\"emptyString\" : \"\"," + + "\"emptyArray\" : []," + "\"emptyObject\" : {}," + + "\"string\" : \"string\"," + "\"number\" : 100," + "\"true\" : true," + + "\"false\" : false," + "\"null\" : null," + + "\"object\" : { \"name\" : \"value\" }," + + "\"array\" : [ \"one\", \"two\" ]" + "}," + + "\"array\" : [ \"string\", 100, true, false, null, { \"name\" : \"value\" }" + + ", [ \"one\", \"two\" ] " + "]," + "\"intPositive\" : 100," + + "\"intNegative\" : -100," + "\"longMax\" : 9223372036854775807," + + "\"longMin\" : -9223372036854775808," + "\"fracPositive\" : 0.5," + + "\"fracNegative\" : -0.5," + "\"expPositive1\" : 7e3," + + "\"expPositive2\" : 7e+3," + "\"expPositive3\" : 9E3," + + "\"expPositive4\" : 9E+3," + "\"expNegative1\" : 7e-3," + + "\"expNegative2\" : 7E-3," + "\"asciiChars\" : \"" + asciiCharacters + + "\"" + "}"; + + public static final String jsonArrayWithAllTypesOfData = "[" + "\"\"," + "[]," + + "{}," + "\"string\"," + "100," + "true," + "false," + "null," + "{" + + "\"emptyString\" : \"\"," + "\"emptyArray\" : []," + + "\"emptyObject\" : {}," + "\"string\" : \"string\"," + + "\"number\" : 100," + "\"true\" : true," + "\"false\" : false," + + "\"null\" : null," + "\"object\" : { \"name\" : \"value\" }," + + "\"array\" : [ \"one\", \"two\" ]" + "}," + + "[ \"string\", 100, true, false, null, { \"name\" : \"value\" }" + + ", [ \"one\", \"two\" ] " + "]," + "100," + "-100," + + "9223372036854775807," + "-9223372036854775808," + "0.5," + "-0.5," + + "7e3," + "7e+3," + "9E3," + "9E+3," + "7e-3," + "7E-3," + "\"" + + asciiCharacters + "\"" + "]"; + + public static final String jsonObjectWithLotsOfNestedObjectsData = "{" + + "\"nested1\" : {" + "\"name1\" : \"value1\"," + "\"nested2\" : {" + + "\"name2\" : \"value2\"," + "\"nested3\" : {" + + "\"name3\" : \"value3\"," + "\"nested4\" : {" + + "\"name4\" : \"value4\"," + "\"nested5\" : {" + + "\"name5\" : \"value5\"," + "\"nested6\" : {" + + "\"name6\" : \"value6\"," + "\"nested7\" : {" + + "\"name7\" : \"value7\"," + "\"nested8\" : {" + + "\"name8\" : \"value8\"," + "\"nested9\" : {" + + "\"name9\" : \"value9\"," + "\"nested10\" : {" + + "\"name10\" : \"value10\"," + "\"nested11\" : {" + + "\"name11\" : \"value11\"," + "\"nested12\" : {" + + "\"name12\" : \"value12\"," + "\"nested13\" : {" + + "\"name13\" : \"value13\"," + "\"nested14\" : {" + + "\"name14\" : \"value14\"," + "\"nested15\" : {" + + "\"name15\" : \"value15\"," + "\"nested16\" : {" + + "\"name16\" : \"value16\"," + "\"nested17\" : {" + + "\"name17\" : \"value17\"," + "\"nested18\" : {" + + "\"name18\" : \"value18\"," + "\"nested19\" : {" + + "\"name19\" : \"value19\"," + "\"nested20\" : {" + + "\"name20\" : \"value20\"," + "\"nested21\" : {" + + "\"name21\" : \"value21\"," + "\"nested22\" : {" + + "\"name22\" : \"value22\"," + "\"nested23\" : {" + + "\"name23\" : \"value23\"," + "\"nested24\" : {" + + "\"name24\" : \"value24\"," + "\"nested25\" : {" + + "\"name25\" : \"value25\"," + "\"nested26\" : {" + + "\"name26\" : \"value26\"," + "\"nested27\" : {" + + "\"name27\" : \"value27\"," + "\"nested28\" : {" + + "\"name28\" : \"value28\"," + "\"nested29\" : {" + + "\"name29\" : \"value29\"," + "\"nested30\" : {" + + "\"name30\" : \"value30\"" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}"; + + public static final String jsonArrayWithLotsOfNestedObjectsData = "[" + "{" + + "\"name1\" : \"value1\"," + "\"nested2\" : {" + + "\"name2\" : \"value2\"," + "\"nested3\" : {" + + "\"name3\" : \"value3\"," + "\"nested4\" : {" + + "\"name4\" : \"value4\"," + "\"nested5\" : {" + + "\"name5\" : \"value5\"," + "\"nested6\" : {" + + "\"name6\" : \"value6\"," + "\"nested7\" : {" + + "\"name7\" : \"value7\"," + "\"nested8\" : {" + + "\"name8\" : \"value8\"," + "\"nested9\" : {" + + "\"name9\" : \"value9\"," + "\"nested10\" : {" + + "\"name10\" : \"value10\"," + "\"nested11\" : {" + + "\"name11\" : \"value11\"," + "\"nested12\" : {" + + "\"name12\" : \"value12\"," + "\"nested13\" : {" + + "\"name13\" : \"value13\"," + "\"nested14\" : {" + + "\"name14\" : \"value14\"," + "\"nested15\" : {" + + "\"name15\" : \"value15\"," + "\"nested16\" : {" + + "\"name16\" : \"value16\"," + "\"nested17\" : {" + + "\"name17\" : \"value17\"," + "\"nested18\" : {" + + "\"name18\" : \"value18\"," + "\"nested19\" : {" + + "\"name19\" : \"value19\"," + "\"nested20\" : {" + + "\"name20\" : \"value20\"," + "\"nested21\" : {" + + "\"name21\" : \"value21\"," + "\"nested22\" : {" + + "\"name22\" : \"value22\"," + "\"nested23\" : {" + + "\"name23\" : \"value23\"," + "\"nested24\" : {" + + "\"name24\" : \"value24\"," + "\"nested25\" : {" + + "\"name25\" : \"value25\"," + "\"nested26\" : {" + + "\"name26\" : \"value26\"," + "\"nested27\" : {" + + "\"name27\" : \"value27\"," + "\"nested28\" : {" + + "\"name28\" : \"value28\"," + "\"nested29\" : {" + + "\"name29\" : \"value29\"," + "\"nested30\" : {" + + "\"name30\" : \"value30\"" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "}" + "]"; + + public static final String jsonArrayWithMultipleArraysData = "[ \"string\", 100, true, false, null, { \"object\" : \"object\" }, [ \"one\"," + + "\"two\" ], [ 100, 7e7, true, false, null, { \"object2\" : \"object2\" } ] ]"; +}
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/JSONP_Util.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/JSONP_Util.java new file mode 100644 index 0000000..94145de --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/JSONP_Util.java
@@ -0,0 +1,2613 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.common; + + +import java.util.*; +import java.io.*; +import java.net.*; +import java.lang.reflect.*; +import java.nio.charset.Charset; + +import java.math.BigInteger; +import java.math.BigDecimal; + +import jakarta.json.*; +import jakarta.json.stream.*; +import jakarta.json.stream.JsonParser.Event.*; +import jakarta.json.JsonValue.ValueType.*; + +public final class JSONP_Util { + + // Charset CONSTANTS for all the supported UTF encodings + public static final Charset UTF_8 = Charset.forName("UTF-8"); + + public static final Charset UTF_16 = Charset.forName("UTF-16"); + + public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); + + public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); + + public static final Charset UTF_32BE = Charset.forName("UTF-32BE"); + + public static final Charset UTF_32LE = Charset.forName("UTF-32LE"); + + // Test Config properties + public static final String FOO_CONFIG = "jakarta.jsonp.tck.common.FOO_CONFIG"; + + // Number of parser errors encountered + private static int parseErrs = 0; + + // A JsonNumber NumberType is now INTEGRAL or NON_INTEGRAL based on + // JsonNumber.isIntegral(). + // The following 2 constant definitions represent these NumberType boolean + // values. + public static final boolean INTEGRAL = true; + + public static final boolean NON_INTEGRAL = false; + + /********************************************************************************* + * void dumpContentsOfResource(String resource) + *********************************************************************************/ + public static void dumpContentsOfResource(String resource) { + System.out.println("Dumping contents of Resource file: " + resource); + BufferedReader reader = null; + try { + InputStream iStream = JSONP_Util.class + .getResourceAsStream("/" + resource); + if (iStream == null) { + System.err.println( + "dumpContentsOfResource: no resource found in classpath or archive named " + + resource); + return; + } + reader = new BufferedReader(new InputStreamReader(iStream)); + String thisLine; + while ((thisLine = reader.readLine()) != null) { + System.out.println(thisLine); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (reader != null) + try { + reader.close(); + } catch (Exception e) { + System.err.println("exception closing stream: " + e); + } + } + } + + /********************************************************************************* + * void dumpFile(String file) + *********************************************************************************/ + public static void dumpFile(String file) { + System.out.println("Dumping contents of file: " + file); + BufferedReader reader = null; + try { + FileInputStream fis = new FileInputStream(file); + if (fis == null) { + System.err.println("dumpFile: no file found named " + file); + return; + } + reader = new BufferedReader(new InputStreamReader(fis)); + String thisLine; + while ((thisLine = reader.readLine()) != null) { + System.out.println(thisLine); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (reader != null) + try { + reader.close(); + } catch (Exception e) { + System.err.println("exception closing stream: " + e); + } + } + } + + /********************************************************************************* + * String getContentsOfResourceAsString(String resource) + *********************************************************************************/ + public static String getContentsOfResourceAsString(String resource) { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try { + InputStream iStream = JSONP_Util.class + .getResourceAsStream("/" + resource); + if (iStream == null) { + System.err.println( + "dumpContentsOfResource: no resource found in classpath or archive named " + + resource); + return null; + } + reader = new BufferedReader(new InputStreamReader(iStream)); + String thisLine; + while ((thisLine = reader.readLine()) != null) { + sb.append(thisLine); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (reader != null) + try { + reader.close(); + } catch (Exception e) { + System.err.println("exception closing stream: " + e); + } + } + return sb.toString(); + } + + /********************************************************************************* + * Reader getReaderFromResource(String resource) + *********************************************************************************/ + public static Reader getReaderFromResource(String resource) { + InputStreamReader reader = null; + try { + InputStream iStream = JSONP_Util.class + .getResourceAsStream("/" + resource); + if (iStream == null) + System.err.println( + "getReaderFromResource: no resource found in classpath or archive named " + + resource); + else + reader = new InputStreamReader(iStream); + } catch (Exception e) { + e.printStackTrace(); + } + return reader; + } + + /********************************************************************************* + * Reader getReaderFromString(String contents) + *********************************************************************************/ + public static Reader getReaderFromString(String contents) { + InputStreamReader reader = null; + try { + InputStream iStream = new ByteArrayInputStream(contents.getBytes(UTF_8)); + if (iStream == null) + System.err.println("getReaderFromString: no input stream"); + else + reader = new InputStreamReader(iStream); + } catch (Exception e) { + e.printStackTrace(); + } + return reader; + } + + /********************************************************************************* + * InputStream getInputStreamFromResource(String resource) + *********************************************************************************/ + public static InputStream getInputStreamFromResource(String resource) { + InputStream iStream = null; + try { + iStream = JSONP_Util.class.getResourceAsStream("/" + resource); + if (iStream == null) + System.err.println( + "getInputStreamFromResource: no resource found in classpath or archive named " + + resource); + } catch (Exception e) { + e.printStackTrace(); + } + return iStream; + } + + /********************************************************************************* + * InputStream getInputStreamFromString(String contents) + *********************************************************************************/ + public static InputStream getInputStreamFromString(String contents) { + InputStream iStream = null; + try { + iStream = new ByteArrayInputStream(contents.getBytes(UTF_8)); + if (iStream == null) + System.err.println("getInputStreamFromString: no input stream"); + } catch (Exception e) { + e.printStackTrace(); + } + return iStream; + } + + /********************************************************************************* + * InputStream getInputStreamFromOutputStream(ByteArrayOutputStream baos) + *********************************************************************************/ + public static InputStream getInputStreamFromOutputStream( + ByteArrayOutputStream baos) { + InputStream iStream = null; + try { + iStream = new ByteArrayInputStream(baos.toByteArray()); + if (iStream == null) + System.err.println("getInputStreamFromOutputStream: no input stream"); + } catch (Exception e) { + e.printStackTrace(); + } + return iStream; + } + + /********************************************************************************* + * String removeWhitespace(String text) + * + * NOTE: This does not remove whitespace of Json text if a quoted string which + * can include whitespace. + *********************************************************************************/ + public static String removeWhitespace(String text) { + StringReader reader = new StringReader(text); + StringWriter writer = new StringWriter(); + try { + boolean quotedString = false; + boolean backslash = false; + int c; + while ((c = reader.read()) != -1) { + // Skip white space if not quoted string + if (!quotedString) { + if (Character.isWhitespace(c)) + continue; + } + writer.write(c); + if (c == '"') { + if (!backslash) + quotedString = !quotedString; + backslash = false; + } else if (c == '\\') + backslash = true; + } + } catch (IOException e) { + e.printStackTrace(); + } + return writer.toString(); + } + + /********************************************************************************* + * JsonNumber createJsonNumber + * + * The following method signatures are available: + * + * o JsonNumber createJsonNumber(double) o JsonNumber createJsonNumber(long) o + * JsonNumber createJsonNumber(int) o JsonNumber createJsonNumber(BigDecimal) + * o JsonNumber createJsonNumber(BigInteger) + *********************************************************************************/ + public static JsonNumber createJsonNumber(double val) { + JsonArray array = Json.createArrayBuilder().add(val).build(); + return array.getJsonNumber(0); + } + + public static JsonNumber createJsonNumber(long val) { + JsonArray array = Json.createArrayBuilder().add(val).build(); + return array.getJsonNumber(0); + } + + public static JsonNumber createJsonNumber(int val) { + JsonArray array = Json.createArrayBuilder().add(val).build(); + return array.getJsonNumber(0); + } + + public static JsonNumber createJsonNumber(BigDecimal val) { + JsonArray array = Json.createArrayBuilder().add(val).build(); + return array.getJsonNumber(0); + } + + public static JsonNumber createJsonNumber(BigInteger val) { + JsonArray array = Json.createArrayBuilder().add(val).build(); + return array.getJsonNumber(0); + } + + /********************************************************************************* + * JsonString createJsonString(String val) + *********************************************************************************/ + public static JsonString createJsonString(String val) { + JsonArray array = Json.createArrayBuilder().add(val).build(); + return array.getJsonString(0); + } + + /********************************************************************************* + * void dumpJsonString(JsonString val) + *********************************************************************************/ + public static void dumpJsonString(JsonString value) { + System.out.println("dumpJsonString->" + toStringJsonString(value)); + } + + /********************************************************************************* + * void dumpJsonArray(JsonArray value) + *********************************************************************************/ + public static void dumpJsonArray(JsonArray value) { + System.out.println("dumpJsonArray->" + toStringJsonArray(value)); + } + + /********************************************************************************* + * void dumpJsonObject(JsonObject value) + *********************************************************************************/ + public static void dumpJsonObject(JsonObject value) { + System.out.println("dumpJsonObject->" + toStringJsonObject(value)); + } + + /********************************************************************************* + * void dumpJsonConstant(JsonValue value) + *********************************************************************************/ + public static void dumpJsonConstant(JsonValue value) { + System.out.println("dumpJsonConstant->" + toStringJsonConstant(value)); + } + + /********************************************************************************* + * void dumpJsonNumber(JsonNumber value) + *********************************************************************************/ + public static void dumpJsonNumber(JsonNumber value) { + System.out.println("dumpJsonNumber->" + toStringJsonNumber(value)); + } + + /********************************************************************************* + * void dumpJsonValue(JsonValue value) + *********************************************************************************/ + public static void dumpJsonValue(JsonValue value) { + if (value instanceof JsonNumber) { + dumpJsonNumber((JsonNumber) value); + } else if (value instanceof JsonString) { + dumpJsonString((JsonString) value); + } else if (value instanceof JsonArray) { + dumpJsonArray((JsonArray) value); + } else if (value instanceof JsonObject) { + dumpJsonObject((JsonObject) value); + } else + dumpJsonConstant(value); + } + + /********************************************************************************* + * String toStringJsonString(JsonString value) + *********************************************************************************/ + public static String toStringJsonString(JsonString value) { + if (value == null) + return ("JsonString is null"); + return ("\"" + value.getString() + "\""); + } + + /********************************************************************************* + * String toStringJsonArray(JsonArray value) + *********************************************************************************/ + public static String toStringJsonArray(JsonArray value) { + if (value == null) + return ("JsonArray is null"); + StringBuilder sb = new StringBuilder(); + sb.append("["); + Iterator<JsonValue> iter = value.iterator(); + String comma = ""; + while (iter.hasNext()) { + sb.append(comma + toStringJsonValue(iter.next())); + if (comma.equals("")) + comma = ","; + } + sb.append("]"); + return (sb.toString()); + } + + /********************************************************************************* + * String toStringJsonObject(JsonObject value) + *********************************************************************************/ + public static String toStringJsonObject(JsonObject value) { + if (value == null) + return ("JsonObject is null"); + StringBuilder sb = new StringBuilder(); + sb.append("{"); + String comma = ""; + for (Map.Entry<String, JsonValue> entry : value.entrySet()) { + sb.append(comma + "\"" + entry.getKey() + "\":" + + toStringJsonValue(entry.getValue())); + if (comma.equals("")) + comma = ","; + } + sb.append("}"); + return (sb.toString()); + } + + /********************************************************************************* + * String toStringJsonConstant(JsonValue value) + *********************************************************************************/ + public static String toStringJsonConstant(JsonValue value) { + if (value == null) + return ("JsonValue is null"); + if (value == JsonValue.FALSE) + return "false"; + else if (value == JsonValue.TRUE) + return "true"; + else if (value == JsonValue.NULL) + return "null"; + else + return "UNKNOWN"; + } + + /********************************************************************************* + * String toStringJsonNumber(JsonNumber value) + *********************************************************************************/ + public static String toStringJsonNumber(JsonNumber value) { + if (value == null) + return ("JsonNumber is null"); + if (value.isIntegral() == INTEGRAL) + return ("" + value.longValue()); + else + return ("" + value.bigDecimalValue()); + } + + /********************************************************************************* + * String toStringJsonValue(JsonValue value) + *********************************************************************************/ + public static String toStringJsonValue(JsonValue value) { + if (value instanceof JsonNumber) { + return toStringJsonNumber((JsonNumber) value); + } else if (value instanceof JsonString) { + return toStringJsonString((JsonString) value); + } else if (value instanceof JsonArray) { + return toStringJsonArray((JsonArray) value); + } else if (value instanceof JsonObject) { + return toStringJsonObject((JsonObject) value); + } else + return toStringJsonConstant(value); + } + + /********************************************************************************* + * void dumpSet(Set<String> set, String msg) + *********************************************************************************/ + public static void dumpSet(Set<String> set, String msg) { + System.out.println("*** Beg: Dumping List contents ***"); + if (msg != null) + System.out.println("*** Message: " + msg); + Iterator iterator = set.iterator(); + System.out.println("Set: ("); + while (iterator.hasNext()) { + System.out.println((String) iterator.next()); + } + System.out.println(")"); + System.out.println("*** End: Dumping Set contents ***"); + } + + /********************************************************************************* + * void dumpSet(Set<String> set) + *********************************************************************************/ + public static void dumpSet(Set<String> set) { + dumpSet(set, null); + } + + /********************************************************************************* + * String toStringSet(Set<String> set) + *********************************************************************************/ + public static String toStringSet(Set<String> set) { + Iterator<String> iter = set.iterator(); + StringBuilder sb = new StringBuilder(); + sb.append("Set: ("); + while (iter.hasNext()) { + sb.append(iter.next()); + if (iter.hasNext()) + sb.append(","); + } + sb.append(")"); + return sb.toString(); + } + + /********************************************************************************* + * boolean assertEqualsSet(Set<String>expSet, Set<String>actSet) + *********************************************************************************/ + public static boolean assertEqualsSet(Set<String> expSet, + Set<String> actSet) { + if (actSet.equals(expSet)) { + System.out.println("Sets are equal - match (Success)"); + System.out.println("Expected: " + toStringSet(expSet)); + System.out.println("Actual: " + toStringSet(actSet)); + return true; + } else { + System.out.println("Sets are not equal - mismatch (Failure)"); + System.err.println("Expected: " + toStringSet(expSet)); + System.err.println("Actual: " + toStringSet(actSet)); + return false; + } + } + + /********************************************************************************* + * void dumpMap(Map<String,JsonValue> map, String msg) + *********************************************************************************/ + public static void dumpMap(Map<String, JsonValue> map, String msg) { + System.out.println("*** Beg: Dumping Map contents ***"); + if (msg != null) + System.out.println("*** Message: " + msg); + System.out.println("Map: {"); + for (Map.Entry<String, JsonValue> entry : map.entrySet()) { + System.out.println( + "\"" + entry.getKey() + "\":" + toStringJsonValue(entry.getValue())); + } + System.out.println("}"); + System.out.println("*** End: Dumping Map contents ***"); + } + + /********************************************************************************* + * void dumpMap(Map<String,JsonValue> map) + *********************************************************************************/ + public static void dumpMap(Map<String, JsonValue> map) { + dumpMap(map, null); + } + + /********************************************************************************* + * String toStringMap(Map<String,JsonValue> map) + *********************************************************************************/ + public static String toStringMap(Map<String, JsonValue> map) { + StringBuilder sb = new StringBuilder(); + sb.append("Map: {"); + String comma = ""; + for (Map.Entry<String, JsonValue> entry : map.entrySet()) { + sb.append(comma + "\"" + entry.getKey() + "\":" + + toStringJsonValue(entry.getValue())); + if (comma.equals("")) + comma = ","; + } + sb.append("}"); + return sb.toString(); + } + + /********************************************************************************* + * boolean assertEqualsMap(Map<String,JsonValue>expMap, + * Map<String,JsonValue>actMap) + *********************************************************************************/ + public static boolean assertEqualsMap(Map<String, JsonValue> expMap, + Map<String, JsonValue> actMap) { + if (actMap.equals(expMap)) { + System.out.println("Maps are equal - match (Success)"); + System.out.println("Expected: " + toStringMap(expMap)); + System.out.println("Actual: " + toStringMap(actMap)); + return true; + } else { + System.out.println("Maps are not equal - mismatch (Failure)"); + System.err.println("Expected: " + toStringMap(expMap)); + System.err.println("Actual: " + toStringMap(actMap)); + return false; + } + } + + /********************************************************************************* + * assertEqualsMap2 + *********************************************************************************/ + public static boolean assertEqualsMap2(Map<String, JsonValue> expMap, + Map<String, JsonValue> actMap) { + System.out.println("*** Comparing Map expMap and Map actMap for equality ***"); + System.out.println("Expected: " + toStringMap(expMap)); + System.out.println("Actual: " + toStringMap(actMap)); + System.out.println("Map expMap size should equal Map actMap size"); + if (expMap.size() != actMap.size()) { + System.err.println("Map sizes are not equal: expMap size " + expMap.size() + + ", actMap size " + actMap.size()); + return false; + } else { + System.out.println("Map sizes are equal with size of " + expMap.size()); + } + for (Map.Entry<String, ?> entry : expMap.entrySet()) { + String key = entry.getKey(); + if (actMap.containsKey(key)) { + if (expMap.get(key) != null && actMap.get(key) != null) { + if (!expMap.get(key).equals(actMap.get(key))) { + System.err.println("key=" + key + ", expMap value " + expMap.get(key) + + " does not equal actMap value " + actMap.get(key)); + return false; + } + } + } else { + System.err.println("actMap does not contain key " + key); + return false; + } + } + System.out.println("Maps expMap and actMap are equal."); + return true; + } + + /********************************************************************************* + * void dumpList(List<JsonValue> list, String msg) + *********************************************************************************/ + public static void dumpList(List<JsonValue> list, String msg) { + System.out.println("*** Beg: Dumping List contents ***"); + if (msg != null) + System.out.println("*** Message: " + msg); + Iterator<JsonValue> iter = list.iterator(); + System.out.println("List: ["); + while (iter.hasNext()) { + System.out.println("" + toStringJsonValue(iter.next())); + } + System.out.println("]"); + System.out.println("*** End: Dumping List contents ***"); + } + + /********************************************************************************* + * void dumpList(List<JsonValue> list) + *********************************************************************************/ + public static void dumpList(List<JsonValue> list) { + dumpList(list, null); + } + + /********************************************************************************* + * String toStringList(List<JsonValue> list) + *********************************************************************************/ + public static String toStringList(List<JsonValue> list) { + Iterator<JsonValue> iter = list.iterator(); + StringBuilder sb = new StringBuilder(); + sb.append("List: ["); + String comma = ""; + while (iter.hasNext()) { + sb.append(comma + toStringJsonValue(iter.next())); + if (comma.equals("")) + comma = ","; + } + sb.append("]"); + return sb.toString(); + } + + /********************************************************************************* + * boolean assertEqualsList(List<JsonValue>expList, List<JsonValue>actList) + *********************************************************************************/ + public static boolean assertEqualsList(List<JsonValue> expList, + List<JsonValue> actList) { + if (actList.equals(expList)) { + System.out.println("Lists are equal - match (Success)"); + System.out.println("Expected: " + toStringList(expList)); + System.out.println("Actual: " + toStringList(actList)); + return true; + } else { + System.out.println("Lists are not equal - mismatch (Failure)"); + System.err.println("Expected: " + toStringList(expList)); + System.err.println("Actual: " + toStringList(actList)); + return false; + } + } + + /********************************************************************************* + * assertEqualsList2 + *********************************************************************************/ + public static boolean assertEqualsList2(List<JsonValue> expList, + List<JsonValue> actList) { + System.out.println( + "*** Comparing contents of List expList and List actList for equality ***"); + System.out.println("Expected: " + toStringList(expList)); + System.out.println("Actual: " + toStringList(actList)); + System.out.println("List expList size should equal List actList size"); + if (expList.size() != actList.size()) { + System.err.println("List sizes are not equal: expList size " + expList.size() + + ", actList size " + actList.size()); + return false; + } + System.out.println("Compare Lists (all elements should MATCH)"); + for (int i = 0; i < expList.size(); i++) { + if (expList.get(i).equals(actList.get(i))) { + System.out.println("expList element " + i + " matches actList element " + i); + } else { + System.err.println( + "expList element " + i + " does not match actList element " + i); + System.err.println("expList[" + i + "]=" + expList.get(i)); + System.err.println("actList[" + i + "]=" + actList.get(i)); + return false; + } + } + System.out.println("Lists are equal (Success)"); + return true; + } + + /********************************************************************************* + * void dumpIterator(Iterator<JsonValue> iterator, String msg) + *********************************************************************************/ + public static void dumpIterator(Iterator<JsonValue> iterator, String msg) { + System.out.println("*** Beg: Dumping Iterator contents ***"); + if (msg != null) + System.out.println("*** Message: " + msg); + System.out.println("Iter: ["); + while (iterator.hasNext()) { + System.out.println("" + toStringJsonValue(iterator.next())); + } + System.out.println("]"); + System.out.println("*** End: Dumping Iterator contents ***"); + } + + /********************************************************************************* + * void dumpIterator(Iterator<JsonValue> iterator) + *********************************************************************************/ + public static void dumpIterator(Iterator<JsonValue> iterator) { + dumpIterator(iterator, null); + } + + /********************************************************************************* + * String toStringIterator(Iterator<JsonValue> iterator) + *********************************************************************************/ + public static String toStringIterator(Iterator<JsonValue> iter) { + StringBuilder sb = new StringBuilder(); + sb.append("Iterator: ["); + while (iter.hasNext()) { + sb.append(toStringJsonValue(iter.next())); + if (iter.hasNext()) + sb.append(","); + } + sb.append("]"); + return sb.toString(); + } + + /********************************************************************************* + * boolean assertEqualsIterator(Iterator<JsonValue>expIt, + * Iterator<JsonValue>actIt) + *********************************************************************************/ + public static boolean assertEqualsIterator(Iterator<JsonValue> expIt, + Iterator<JsonValue> actIt) { + boolean pass = true; + + System.out.println( + "*** Comparing contents of Iterator expIt and Iterator actIt for equality ***"); + int i = 0; + while (expIt.hasNext()) { + if (!actIt.hasNext()) { + System.err.println( + "Iterator expIt contains more elements than Iterator actIt"); + return false; + } + ++i; + JsonValue value1 = expIt.next(); + JsonValue value2 = actIt.next(); + if (assertEqualsJsonValues(value1, value2)) { + System.out.println("Iterator expIt element " + i + + " matches Iterator actIt element " + i); + } else { + System.err.println("Iterator expIt element " + i + + " does not match Iterator actIt element " + i); + pass = false; + } + } + if (actIt.hasNext()) { + System.err.println("Iterator actIt contains more elements than Iterator expIt"); + return false; + } + if (pass) + System.out.println("Iterators are equal (Success)"); + else + System.out.println("Iterators are not equal (Failure)"); + return pass; + } + + /********************************************************************************* + * boolean assertEqualsEmptyArrayList(List<JsonValue> actual) + *********************************************************************************/ + public static boolean assertEqualsEmptyArrayList(List<JsonValue> actual) { + if (actual.isEmpty()) { + System.out.println("Array List is empty - expected"); + return true; + } else { + System.err.println("Array List is not empty - unexpected"); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsEmptyObjectMap(Map<String, JsonValue> actual) + *********************************************************************************/ + public static boolean assertEqualsEmptyObjectMap( + Map<String, JsonValue> actual) { + if (actual.isEmpty()) { + System.out.println("Object Map is empty - expected"); + return true; + } else { + System.err.println("Object Map is not empty - unexpected"); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsEmptyIterator(Map<String, JsonValue> actual) + *********************************************************************************/ + public static boolean assertEqualsEmptyIterator(Iterator<JsonValue> actual) { + if (!actual.hasNext()) { + System.out.println("Iterator is empty - expected"); + return true; + } else { + System.err.println("Iterator is not empty - unexpected"); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsJsonText(String expected, String actual) + *********************************************************************************/ + public static boolean assertEqualsJsonText(String expected, String actual) { + if (actual.equals(expected)) { + System.out.println("JSON text match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("JSON text mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsJsonArrays(JsonArray expected, JsonArray actual) + *********************************************************************************/ + public static boolean assertEqualsJsonArrays(JsonArray expected, + JsonArray actual) { + if (actual.equals(expected)) { + System.out.println("JsonArray match"); + System.out.println("Expected: " + toStringJsonArray(expected)); + System.out.println("Actual: " + toStringJsonArray(actual)); + return true; + } else { + System.err.println("JsonArray mismatch"); + System.err.println("Expected: " + toStringJsonArray(expected)); + System.err.println("Actual: " + toStringJsonArray(actual)); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsJsonObjects(JsonObject expected, JsonObject actual) + *********************************************************************************/ + public static boolean assertEqualsJsonObjects(JsonObject expected, + JsonObject actual) { + if (actual.equals(expected)) { + System.out.println("JsonObject match"); + System.out.println("Expected: " + toStringJsonObject(expected)); + System.out.println("Actual: " + toStringJsonObject(actual)); + return true; + } else { + System.err.println("JsonObject mismatch"); + System.err.println("Expected: " + toStringJsonObject(expected)); + System.err.println("Actual: " + toStringJsonObject(actual)); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsJsonNumbers(JsonNumber expected, JsonNumber actual) + *********************************************************************************/ + public static boolean assertEqualsJsonNumbers(JsonNumber expected, + JsonNumber actual) { + boolean pass = true; + + if (actual.equals(expected)) { + System.out.println("JsonNumber match"); + System.out.println("Expected: " + toStringJsonNumber(expected)); + System.out.println("Actual: " + toStringJsonNumber(actual)); + return true; + } else { + System.err.println("JsonNumber mismatch"); + System.err.println("Expected: " + toStringJsonNumber(expected)); + System.err.println("Actual: " + toStringJsonNumber(actual)); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsJsonStrings(JsonString expected, JsonString actual) + *********************************************************************************/ + public static boolean assertEqualsJsonStrings(JsonString expected, + JsonString actual) { + boolean pass = true; + + if (actual.equals(expected)) { + System.out.println("JsonString match"); + System.out.println("Expected: " + toStringJsonString(expected)); + System.out.println("Actual: " + toStringJsonString(actual)); + return true; + } else { + System.err.println("JsonString mismatch"); + System.err.println("Expected: " + toStringJsonString(expected)); + System.err.println("Actual: " + toStringJsonString(actual)); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsJsonValues(JsonValue expected, JsonValue actual) + *********************************************************************************/ + public static boolean assertEqualsJsonValues(JsonValue expected, + JsonValue actual) { + boolean pass = true; + + // Comparing JsonNumbers + if (expected instanceof JsonNumber) { + if (!(actual instanceof JsonNumber)) { + System.err.println("expected type does not match actual type"); + System.err.println("expected=" + toStringJsonValue(expected)); + System.err.println("actual= " + toStringJsonValue(actual)); + pass = false; + } else { + pass = assertEqualsJsonNumbers((JsonNumber) expected, + (JsonNumber) actual); + } + // Comparing JsonStrings + } else if (expected instanceof JsonString) { + if (!(actual instanceof JsonString)) { + System.err.println("expected type does not match actual type"); + System.err.println("expected=" + toStringJsonValue(expected)); + System.err.println("actual= " + toStringJsonValue(actual)); + pass = false; + } else { + pass = assertEqualsJsonStrings((JsonString) expected, + (JsonString) actual); + } + // Comparing JsonArrays + } else if (expected instanceof JsonArray) { + if (!(actual instanceof JsonArray)) { + System.err.println("expected type does not match actual type"); + System.err.println("expected=" + toStringJsonValue(expected)); + System.err.println("actual= " + toStringJsonValue(actual)); + pass = false; + } else { + pass = assertEqualsJsonArrays((JsonArray) expected, (JsonArray) actual); + } + // Comparing JsonObjects + } else if (expected instanceof JsonObject) { + if (!(actual instanceof JsonObject)) { + System.err.println("expected type does not match actual type"); + System.err.println("expected=" + toStringJsonValue(expected)); + System.err.println("actual= " + toStringJsonValue(actual)); + pass = false; + } else { + pass = assertEqualsJsonObjects((JsonObject) expected, + (JsonObject) actual); + } + // Comparing JsonValues + } else if (expected.equals(actual)) { + System.out.println("expected matches actual"); + System.out.println("expected=" + toStringJsonValue(expected)); + System.out.println("actual= " + toStringJsonValue(actual)); + } else { + System.err.println("expected does not match actual"); + System.err.println("expected=" + toStringJsonValue(expected)); + System.err.println("actual= " + toStringJsonValue(actual)); + pass = false; + } + return pass; + } + + /********************************************************************************* + * boolean assertEqualsJsonValueType(JsonValue.ValueType + * expected,JsonValue.ValueType actual) + *********************************************************************************/ + public static boolean assertEqualsJsonValueType(JsonValue.ValueType expected, + JsonValue.ValueType actual) { + if (actual == expected) { + System.out.println("JsonValue.ValueType match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("JsonValue.ValueType mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsJsonNumberType(boolean expected,boolean actual) + *********************************************************************************/ + public static boolean assertEqualsJsonNumberType(boolean expected, + boolean actual) { + if (actual == expected) { + System.out.println("Json NumberType match"); + System.out.println("Expected: " + toStringJsonNumberType(expected)); + System.out.println("Actual: " + toStringJsonNumberType(actual)); + return true; + } else { + System.err.println("Json NumberType mismatch"); + System.err.println("Expected: " + toStringJsonNumberType(expected)); + System.err.println("Actual: " + toStringJsonNumberType(actual)); + return false; + } + } + + /********************************************************************************* + * boolean assertEqualsJsonNumberTypes(boolean expected[],boolean actual) + *********************************************************************************/ + public static boolean assertEqualsJsonNumberTypes(boolean expected[], + boolean actual) { + for (int i = 0; i < expected.length; i++) { + if (actual == expected[i]) { + System.out.println("Json NumberType match"); + System.out.println("Expected: " + toStringJsonNumberType(expected[i])); + System.out.println("Actual: " + toStringJsonNumberType(actual)); + return true; + } + } + System.err.println("Json NumberType mismatch"); + System.err.println("Expected: " + toStringJsonNumberTypes(expected)); + System.err.println("Actual: " + toStringJsonNumberType(actual)); + return false; + } + + /********************************************************************************* + * String toStringJsonNumberType(boolean numberType) + *********************************************************************************/ + public static String toStringJsonNumberType(boolean numberType) { + if (numberType == INTEGRAL) + return "INTEGRAL"; + else + return "NON_INTEGRAL"; + } + + /********************************************************************************* + * String toStringJsonNumberTypes(boolean expected[]) + *********************************************************************************/ + public static String toStringJsonNumberTypes(boolean expected[]) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < expected.length; i++) { + sb.append("" + toStringJsonNumberType(expected[i])); + if (i + 1 < expected.length) + sb.append("|"); + } + return sb.toString(); + } + + /********************************************************************************* + * boolean assertEquals(Object, Object) + *********************************************************************************/ + public static boolean assertEquals(Object expected, Object actual) { + if (actual.equals(expected)) { + System.out.println("Object match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("Object mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(boolean, boolean) + *********************************************************************************/ + public static boolean assertEquals(boolean expected, boolean actual) { + if (actual == expected) { + System.out.println("boolean match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("boolean mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(short, short) + *********************************************************************************/ + public static boolean assertEquals(short expected, short actual) { + if (actual == expected) { + System.out.println("short match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("short mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(int, int) + *********************************************************************************/ + public static boolean assertEquals(int expected, int actual) { + if (actual == expected) { + System.out.println("int match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("int mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(long, long) + *********************************************************************************/ + public static boolean assertEquals(long expected, long actual) { + if (actual == expected) { + System.out.println("long match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("long mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(float, float) + *********************************************************************************/ + public static boolean assertEquals(float expected, float actual) { + if (actual == expected) { + System.out.println("float match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("float mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(double, double) + *********************************************************************************/ + public static boolean assertEquals(double expected, double actual) { + if (actual == expected) { + System.out.println("double match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("double mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(BigDecimal, BigDecimal) + *********************************************************************************/ + public static boolean assertEquals(BigDecimal expected, BigDecimal actual) { + if (actual.equals(expected)) { + System.out.println("BigDecimal match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("BigDecimal mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(BigInteger, BigInteger) + *********************************************************************************/ + public static boolean assertEquals(BigInteger expected, BigInteger actual) { + if (actual.equals(expected)) { + System.out.println("BigInteger match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("BigInteger mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(String, String) + *********************************************************************************/ + public static boolean assertEquals(String expected, String actual) { + if (actual.equals(expected)) { + System.out.println("String match"); + System.out.println("Expected: " + expected); + System.out.println("Actual: " + actual); + return true; + } else { + System.err.println("String mismatch"); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + return false; + } + } + + /********************************************************************************* + * boolean assertEquals(JsonValue, JsonValue) + *********************************************************************************/ + public static boolean assertEquals(JsonValue expected, JsonValue actual) { + if (actual.equals(expected)) { + System.out.println("JsonValue match"); + System.out.println("Expected: " + toStringJsonValue(expected)); + System.out.println("Actual: " + toStringJsonValue(actual)); + return true; + } else { + System.err.println("JsonValue mismatch"); + System.err.println("Expected: " + toStringJsonValue(expected)); + System.err.println("Actual: " + toStringJsonValue(actual)); + return false; + } + } + + /********************************************************************************* + * String getNumberTypeString(boolean numberType) + *********************************************************************************/ + public static String getNumberTypeString(boolean numberType) { + if (numberType == INTEGRAL) + return "INTEGRAL"; + else + return "NON_INTEGRAL"; + } + + /********************************************************************************* + * boolean getNumberType(String numberType) + *********************************************************************************/ + public static boolean getNumberType(String numberType) { + if (numberType.equals("INTEGRAL")) + return INTEGRAL; + else + return NON_INTEGRAL; + } + + /********************************************************************************* + * String getValueTypeString(JsonValue.ValueType valueType) + *********************************************************************************/ + public static String getValueTypeString(JsonValue.ValueType valueType) { + switch (valueType) { + case ARRAY: + return "ARRAY"; + case FALSE: + return "FALSE"; + case NULL: + return "NULL"; + case NUMBER: + return "NUMBER"; + case OBJECT: + return "OBJECT"; + case STRING: + return "STRING"; + case TRUE: + return "TRUE"; + default: + return null; + } + } + + /********************************************************************************* + * JsonValue.ValueType getValueType(String valueType) + *********************************************************************************/ + public static JsonValue.ValueType getValueType(String valueType) { + if (valueType.equals("ARRAY")) + return JsonValue.ValueType.ARRAY; + if (valueType.equals("FALSE")) + return JsonValue.ValueType.FALSE; + if (valueType.equals("NULL")) + return JsonValue.ValueType.NULL; + if (valueType.equals("NUMBER")) + return JsonValue.ValueType.NUMBER; + if (valueType.equals("OBJECT")) + return JsonValue.ValueType.OBJECT; + if (valueType.equals("STRING")) + return JsonValue.ValueType.STRING; + if (valueType.equals("TRUE")) + return JsonValue.ValueType.TRUE; + else + return null; + } + + /********************************************************************************* + * void dumpEventType(JsonParser.Event eventType) + *********************************************************************************/ + public static void dumpEventType(JsonParser.Event eventType) { + System.out.println("JsonParser.Event=" + eventType); + } + + /********************************************************************************* + * getEventTypeString(JsonParser.Event eventType) + *********************************************************************************/ + public static String getEventTypeString(JsonParser.Event eventType) { + switch (eventType) { + case START_ARRAY: + return "START_ARRAY"; + case START_OBJECT: + return "START_OBJECT"; + case KEY_NAME: + return "KEY_NAME"; + case VALUE_STRING: + return "VALUE_STRING"; + case VALUE_NUMBER: + return "VALUE_NUMBER"; + case VALUE_TRUE: + return "VALUE_TRUE"; + case VALUE_FALSE: + return "VALUE_FALSE"; + case VALUE_NULL: + return "VALUE_NULL"; + case END_OBJECT: + return "END_OBJECT"; + case END_ARRAY: + return "END_ARRAY"; + default: + return null; + } + } + + /********************************************************************************* + * JsonParser.Event getEventType(String eventType) + *********************************************************************************/ + public static JsonParser.Event getEventType(String eventType) { + if (eventType.equals("START_ARRAY")) + return JsonParser.Event.START_ARRAY; + if (eventType.equals("START_OBJECT")) + return JsonParser.Event.START_OBJECT; + if (eventType.equals("KEY_NAME")) + return JsonParser.Event.KEY_NAME; + if (eventType.equals("VALUE_STRING")) + return JsonParser.Event.VALUE_STRING; + if (eventType.equals("VALUE_NUMBER")) + return JsonParser.Event.VALUE_NUMBER; + if (eventType.equals("VALUE_TRUE")) + return JsonParser.Event.VALUE_TRUE; + if (eventType.equals("VALUE_FALSE")) + return JsonParser.Event.VALUE_FALSE; + if (eventType.equals("VALUE_NULL")) + return JsonParser.Event.VALUE_NULL; + if (eventType.equals("END_OBJECT")) + return JsonParser.Event.END_OBJECT; + if (eventType.equals("END_ARRAY")) + return JsonParser.Event.END_ARRAY; + else + return null; + } + + /********************************************************************************* + * String getConfigName(String configValue) + *********************************************************************************/ + public static String getConfigName(String configValue) { + if (configValue.equals(JsonGenerator.PRETTY_PRINTING)) + return "JsonGenerator.PRETTY_PRINTING"; + else if (configValue.equals(JSONP_Util.FOO_CONFIG)) + return "JSONP_Util.FOO_CONFIG"; + else + return null; + } + + /********************************************************************************* + * String getConfigValue(String configProp) + *********************************************************************************/ + public static String getConfigValue(String configProp) { + if (configProp.equals("JsonGenerator.PRETTY_PRINING")) + return JsonGenerator.PRETTY_PRINTING; + else if (configProp.equals("JSONP_Util.FOO_CONFIG")) + return JSONP_Util.FOO_CONFIG; + else + return null; + } + + /********************************************************************************* + * void dumpConfigMap(Map<String,?> map, String msg) + *********************************************************************************/ + public static void dumpConfigMap(Map<String, ?> map, String msg) { + System.out.println("*** Beg: Dumping Config Map contents ***"); + if (msg != null) + System.out.println("*** Message: " + msg); + for (Map.Entry<String, ?> entry : map.entrySet()) { + System.out.println("\"" + entry.getKey() + "\":" + entry.getValue()); + } + System.out.println("*** End: Dumping Config Map contents ***"); + } + + /********************************************************************************* + * void dumpConfigMap(Map<String,?> map) + *********************************************************************************/ + public static void dumpConfigMap(Map<String, ?> map) { + dumpConfigMap(map, null); + } + + /********************************************************************************* + * boolean doConfigCheck(Map<String,?> config, int expectedSize) + *********************************************************************************/ + public static boolean doConfigCheck(Map<String, ?> config, int expectedSize) { + return doConfigCheck(config, expectedSize, null); + } + + public static boolean doConfigCheck(Map<String, ?> config, int expectedSize, + String[] expectedProps) { + boolean pass = true; + dumpConfigMap(config); + System.out.println("Checking factory configuration property size"); + if (config.size() != expectedSize) { + System.err.println("Expecting no of properties=" + expectedSize + ", got=" + + config.size()); + pass = false; + } else { + System.out.println("Expecting no of properties=" + expectedSize + ", got=" + + config.size()); + } + if (expectedSize != 0 && expectedProps != null) { + System.out.println("Checking factory configuration property name and value"); + for (int i = 0; i < expectedProps.length; i++) { + if (config.containsKey(expectedProps[i])) { + System.out.println("Does contain key: " + expectedProps[i] + " - expected."); + if (!JSONP_Util.assertEquals(true, config.get(expectedProps[i]))) { + pass = false; + } + } else { + System.err.println( + "Does not contain key: " + expectedProps[i] + " - unexpected."); + pass = false; + } + } + } + return pass; + } + + /********************************************************************************* + * boolean isEmptyConfig(Map<String, ?> config) + *********************************************************************************/ + public boolean isEmptyConfig(Map<String, ?> config) { + System.out.println("isEmptyConfig"); + return config.isEmpty(); + } + + /********************************************************************************* + * Map<String, ?> getEmptyConfig() + *********************************************************************************/ + public static Map<String, ?> getEmptyConfig() { + System.out.println("getEmptyConfig"); + Map<String, Object> config = new HashMap<String, Object>(); + return config; + } + + /********************************************************************************* + * Map<String, ?> getPrettyPrintingConfig() + *********************************************************************************/ + public static Map<String, ?> getPrettyPrintingConfig() { + System.out.println("getPrettyPrintConfig"); + Map<String, Object> config = new HashMap<String, Object>(); + System.out.println("Added property: JsonGenerator.PRETTY_PRINTING"); + config.put(JsonGenerator.PRETTY_PRINTING, true); + return config; + } + + /********************************************************************************* + * Map<String, ?> getFooConfig() + *********************************************************************************/ + public static Map<String, ?> getFooConfig() { + System.out.println("getFooConfig"); + Map<String, Object> config = new HashMap<String, Object>(); + System.out.println("Added property: JSONP_Util.FOO_CONFIG"); + config.put(JSONP_Util.FOO_CONFIG, true); + return config; + } + + /********************************************************************************* + * Map<String, ?> getAllConfig() + *********************************************************************************/ + public static Map<String, ?> getAllConfig() { + System.out.println("getAllConfig"); + Map<String, Object> config = new HashMap<String, Object>(); + System.out.println("Added property: JsonGenerator.PRETTY_PRINTING"); + config.put(JsonGenerator.PRETTY_PRINTING, true); + System.out.println("Added property: JSONP_Util.FOO_CONFIG"); + config.put(JSONP_Util.FOO_CONFIG, true); + return config; + } + + /********************************************************************************* + * JsonObject createJsonObjectFromString(String jsonObjData) + *********************************************************************************/ + public static JsonObject createJsonObjectFromString(String jsonObjData) { + JsonReader reader = null; + JsonObject object = null; + try { + reader = Json.createReader(new StringReader(jsonObjData)); + object = reader.readObject(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (reader != null) + reader.close(); + } + return object; + } + + /********************************************************************************* + * JsonArray createJsonArrayFromString(String jsonArrData) + *********************************************************************************/ + public static JsonArray createJsonArrayFromString(String jsonArrData) { + JsonReader reader = null; + JsonArray array = null; + try { + reader = Json.createReader(new StringReader(jsonArrData)); + array = reader.readArray(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (reader != null) + reader.close(); + } + return array; + } + + /********************************************************************************* + * void writeJsonObjectFromString(JsonWriter writer, String jsonObjData) + *********************************************************************************/ + public static void writeJsonObjectFromString(JsonWriter writer, + String jsonObjData) { + try { + JsonObject jsonObject = createJsonObjectFromString(jsonObjData); + writer.writeObject(jsonObject); + writer.close(); + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + } + } + + /********************************************************************************* + * void writeJsonArrayFromString(JsonWriter writer, String jsonArrData) + *********************************************************************************/ + public static void writeJsonArrayFromString(JsonWriter writer, + String jsonArrData) { + try { + JsonArray jsonArray = createJsonArrayFromString(jsonArrData); + writer.writeArray(jsonArray); + writer.close(); + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + } + } + + /********************************************************************************* + * void testKeyStringValue(JsonParser parser, String name, String value) + *********************************************************************************/ + public static void testKeyStringValue(JsonParser parser, String name, + String value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.VALUE_STRING) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_STRING) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } + String keyvalue = parser.getString(); + if (!keyvalue.equals(value)) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testKeyIntegerValue(JsonParser parser, String name, int value) + *********************************************************************************/ + public static void testKeyIntegerValue(JsonParser parser, String name, + int value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.VALUE_NUMBER) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_NUMBER) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + int keyvalue = parser.getInt(); + if (keyvalue != value) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testKeyDoubleValue(JsonParser parser, String name, double value) + *********************************************************************************/ + public static void testKeyDoubleValue(JsonParser parser, String name, + double value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.VALUE_NUMBER) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_NUMBER) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + double keyvalue = parser.getBigDecimal().doubleValue(); + if (keyvalue != value) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testKeyLongValue(JsonParser parser, String name, long value) + *********************************************************************************/ + public static void testKeyLongValue(JsonParser parser, String name, + long value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.VALUE_NUMBER) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_NUMBER) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + long keyvalue = parser.getLong(); + if (keyvalue != value) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testKeyBigDecimalValue(JsonParser parser, String name, BigDecimal + * value) + *********************************************************************************/ + public static void testKeyBigDecimalValue(JsonParser parser, String name, + BigDecimal value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.VALUE_NUMBER) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_NUMBER) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + BigDecimal keyvalue = parser.getBigDecimal(); + if (keyvalue != value) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testKeyTrueValue(JsonParser parser, String name) + *********************************************************************************/ + public static void testKeyTrueValue(JsonParser parser, String name) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.VALUE_TRUE) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_TRUE) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + } + + /********************************************************************************* + * void testKeyFalseValue(JsonParser parser, String name) + *********************************************************************************/ + public static void testKeyFalseValue(JsonParser parser, String name) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.VALUE_FALSE) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_FALSE) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + } + + /********************************************************************************* + * void testKeyNullValue(JsonParser parser, String name) + *********************************************************************************/ + public static void testKeyNullValue(JsonParser parser, String name) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.VALUE_NULL) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_NULL) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + } + + /********************************************************************************* + * void testKeyStartObjectValue(JsonParser parser, String name) + *********************************************************************************/ + public static void testKeyStartObjectValue(JsonParser parser, String name) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.START_OBJECT) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.START_OBJECT) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + } + + /********************************************************************************* + * void testKeyStartArrayValue(JsonParser parser, String name) + *********************************************************************************/ + public static void testKeyStartArrayValue(JsonParser parser, String name) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + + if (e != JsonParser.Event.KEY_NAME) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.KEY_NAME) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyname = parser.getString(); + if (!name.equals(keyname)) { + System.err.println("Expected keyname: " + name + ", got keyname: " + keyname); + parseErrs++; + } else { + System.out.println("Got expected keyname: " + keyname); + } + + if (!checkNextParserEvent(parser)) + return; + e = parser.next(); + if (e != JsonParser.Event.START_ARRAY) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.START_ARRAY) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + } + + /********************************************************************************* + * boolean checkNextParserEvent(JsonParser parser) + *********************************************************************************/ + public static boolean checkNextParserEvent(JsonParser parser) { + if (!parser.hasNext()) { + System.err.println("no next parser event found - unexpected"); + parseErrs++; + return false; + } else + return true; + } + + /********************************************************************************* + * JsonParser.Event getNextParserEvent(JsonParser parser) + *********************************************************************************/ + public static JsonParser.Event getNextParserEvent(JsonParser parser) { + if (parser.hasNext()) + return parser.next(); + else + return null; + } + + /********************************************************************************* + * JsonParser.Event getNextSpecificParserEvent(JsonParser parser, + * JsonParser.Event thisEvent) + *********************************************************************************/ + public static JsonParser.Event getNextSpecificParserEvent(JsonParser parser, + JsonParser.Event thisEvent) { + while (parser.hasNext()) { + JsonParser.Event event = parser.next(); + if (event == thisEvent) + return event; + } + return null; + } + + /********************************************************************************* + * void testEventType(JsonParser parser, JsonParser.Event expEvent) + *********************************************************************************/ + public static void testEventType(JsonParser parser, + JsonParser.Event expEvent) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + if (e != expEvent) { + System.err.println("Expected event: " + getEventTypeString(expEvent) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + } + + /********************************************************************************* + * void testStringValue(JsonParser parser, String value) + *********************************************************************************/ + public static void testStringValue(JsonParser parser, String value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + if (e != JsonParser.Event.VALUE_STRING) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_STRING) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + String keyvalue = parser.getString(); + if (!keyvalue.equals(value)) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testIntegerValue(JsonParser parser, int value) + *********************************************************************************/ + public static void testIntegerValue(JsonParser parser, int value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + if (e != JsonParser.Event.VALUE_NUMBER) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_NUMBER) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + int keyvalue = parser.getInt(); + if (keyvalue != value) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testDoubleValue(JsonParser parser, double value) + *********************************************************************************/ + public static void testDoubleValue(JsonParser parser, double value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + if (e != JsonParser.Event.VALUE_NUMBER) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_NUMBER) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + double keyvalue = parser.getBigDecimal().doubleValue(); + if (keyvalue != value) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testLongValue(JsonParser parser, long value) + *********************************************************************************/ + public static void testLongValue(JsonParser parser, long value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + if (e != JsonParser.Event.VALUE_NUMBER) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_NUMBER) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + long keyvalue = parser.getLong(); + if (keyvalue != value) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testBigDecimalValue(JsonParser parser, BigDecimal value) + *********************************************************************************/ + public static void testBigDecimalValue(JsonParser parser, BigDecimal value) { + if (!checkNextParserEvent(parser)) + return; + JsonParser.Event e = parser.next(); + if (e != JsonParser.Event.VALUE_NUMBER) { + System.err.println( + "Expected event: " + getEventTypeString(JsonParser.Event.VALUE_NUMBER) + + ", got event: " + getEventTypeString(e)); + parseErrs++; + } else { + System.out.println("Got expected event: " + getEventTypeString(e)); + } + BigDecimal keyvalue = parser.getBigDecimal(); + if (keyvalue != value) { + System.err.println( + "Expected keyvalue: " + value + ", got keyvalue: " + keyvalue); + parseErrs++; + } else { + System.out.println("Got expected keyvalue: " + keyvalue); + } + } + + /********************************************************************************* + * void testTrueValue(JsonParser parser, JsonParser.Event expEvent) + *********************************************************************************/ + public static void testTrueValue(JsonParser parser, + JsonParser.Event expEvent) { + testEventType(parser, expEvent); + } + + /********************************************************************************* + * void testFalseValue(JsonParser parser, JsonParser.Event expEvent) + *********************************************************************************/ + public static void testFalseValue(JsonParser parser, + JsonParser.Event expEvent) { + testEventType(parser, expEvent); + } + + /********************************************************************************* + * void testNullValue(JsonParser parser, JsonParser.Event expEvent) + *********************************************************************************/ + public static void testNullValue(JsonParser parser, + JsonParser.Event expEvent) { + testEventType(parser, expEvent); + } + + /********************************************************************************* + * resetParseErrs() + *********************************************************************************/ + public static void resetParseErrs() { + parseErrs = 0; + } + + /********************************************************************************* + * int getParseErrs() + *********************************************************************************/ + public static int getParseErrs() { + return parseErrs; + } + + /********************************************************************************* + * String convertUnicodeCharToString(Char c) + * + * Convert unicode to string value of form U+NNNN where NNNN are 4 hex digits + * + * Use a binary or with hex value '0x10000' when converting unicode char to + * hex string and remove 1st char to get the 4 hex digits we need. + *********************************************************************************/ + public static String convertUnicodeCharToString(char c) { + return "\\u" + Integer.toHexString((int) c | 0x10000).substring(1); + } + + /********************************************************************************* + * boolean isUnicodeControlChar(Char c) + * + * The following unicode control chars: + * + * U+0000 - U+001F and U+007F U+0080 - U+009F + *********************************************************************************/ + public static boolean isUnicodeControlChar(char c) { + + if ((c >= '\u0000' && c <= '\u001F') || (c == '\u007F') + || (c >= '\u0080' && c <= '\u009F')) + return true; + else + return false; + } + + /********************************************************************************* + * void writeStringToFile(String string, String file, String encoding) + *********************************************************************************/ + public static void writeStringToFile(String string, String file, + String encoding) { + try { + FileOutputStream fos = new FileOutputStream(file); + Writer out = new OutputStreamWriter(fos, encoding); + out.write(string); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /********************************************************************************* + * String readStringFromFile(String file, String encoding) + *********************************************************************************/ + public static String readStringFromFile(String file, String encoding) { + StringBuffer buffer = new StringBuffer(); + try { + FileInputStream fis = new FileInputStream(file); + InputStreamReader isr = new InputStreamReader(fis, encoding); + Reader in = new BufferedReader(isr); + int ch; + while ((ch = in.read()) > -1) { + buffer.append((char) ch); + } + in.close(); + return buffer.toString(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /********************************************************************************* + * void writeStringToStream(String string, OutputStream os, String encoding) + *********************************************************************************/ + public static void writeStringToStream(String string, OutputStream os, + String encoding) { + try { + Writer out = new OutputStreamWriter(os, encoding); + out.write(string); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /********************************************************************************* + * String readStringFromStream(InputStream is, String encoding) + *********************************************************************************/ + public static String readStringFromStream(InputStream is, String encoding) { + StringBuffer buffer = new StringBuffer(); + try { + InputStreamReader isr = new InputStreamReader(is, encoding); + Reader in = new BufferedReader(isr); + int ch; + while ((ch = in.read()) > -1) { + buffer.append((char) ch); + } + in.close(); + return buffer.toString(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /********************************************************************************* + * void writeStringToFile(String string, String file, Charset charset) + *********************************************************************************/ + public static void writeStringToFile(String string, String file, + Charset charset) { + try { + FileOutputStream fos = new FileOutputStream(file); + Writer out = new OutputStreamWriter(fos, charset); + out.write(string); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /********************************************************************************* + * String readStringFromFile(String file, Charset charset) + *********************************************************************************/ + public static String readStringFromFile(String file, Charset charset) { + StringBuffer buffer = new StringBuffer(); + try { + FileInputStream fis = new FileInputStream(file); + InputStreamReader isr = new InputStreamReader(fis, charset); + Reader in = new BufferedReader(isr); + int ch; + while ((ch = in.read()) > -1) { + buffer.append((char) ch); + } + in.close(); + return buffer.toString(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /********************************************************************************* + * void writeStringToStream(String string, OutputStream os, Charset charset) + *********************************************************************************/ + public static void writeStringToStream(String string, OutputStream os, + Charset charset) { + try { + Writer out = new OutputStreamWriter(os, charset); + out.write(string); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /********************************************************************************* + * String readStringFromStream(InputStream is, Charset charset) + *********************************************************************************/ + public static String readStringFromStream(InputStream is, Charset charset) { + StringBuffer buffer = new StringBuffer(); + try { + InputStreamReader isr = new InputStreamReader(is, charset); + Reader in = new BufferedReader(isr); + int ch; + while ((ch = in.read()) > -1) { + buffer.append((char) ch); + } + in.close(); + return buffer.toString(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /********************************************************************************* + * Charset getCharset(String encoding) + *********************************************************************************/ + public static Charset getCharset(String encoding) { + Charset cs = null; + + try { + cs = Charset.forName(encoding); + } catch (Exception e) { + e.printStackTrace(); + } + return cs; + } + + /********************************************************************************* + * void dumpLocation(JsonLocation location) + *********************************************************************************/ + public static void dumpLocation(JsonLocation location) { + if (location != null) { + System.out.println("JsonLocation info: lineNumber=" + location.getLineNumber() + + ", columnNumber=" + location.getColumnNumber() + + ", streamOffset=" + location.getStreamOffset()); + } else { + System.out.println("JsonLocation is null - no location info"); + } + } + + /********************************************************************************* + * void dumpLocation(JsonParser parser) + *********************************************************************************/ + public static void dumpLocation(JsonParser parser) { + dumpLocation(parser.getLocation()); + } + + /********************************************************************************* + * boolean assertEquals(JsonLocation, JsonLocation) + *********************************************************************************/ + public static boolean assertEquals(JsonLocation expLoc, JsonLocation actLoc) { + if (expLoc.getLineNumber() == actLoc.getLineNumber() + && expLoc.getColumnNumber() == actLoc.getColumnNumber() + && expLoc.getStreamOffset() == actLoc.getStreamOffset()) { + System.out.println("JsonLocations equal - match (Success)"); + System.out.println( + "Expected: JsonLocation info: lineNumber=" + expLoc.getLineNumber() + + ", columnNumber=" + expLoc.getColumnNumber() + ", streamOffset=" + + expLoc.getStreamOffset()); + System.out.println( + "Actual: JsonLocation info: lineNumber=" + actLoc.getLineNumber() + + ", columnNumber=" + actLoc.getColumnNumber() + ", streamOffset=" + + actLoc.getStreamOffset()); + return true; + } else { + System.err.println("JsonLocations not equal - mismatch (Failure)"); + System.err.println( + "Expected: JsonLocation info: lineNumber=" + expLoc.getLineNumber() + + ", columnNumber=" + expLoc.getColumnNumber() + ", streamOffset=" + + expLoc.getStreamOffset()); + System.err.println( + "Actual: JsonLocation info: lineNumber=" + actLoc.getLineNumber() + + ", columnNumber=" + actLoc.getColumnNumber() + ", streamOffset=" + + actLoc.getStreamOffset()); + return false; + } + } + + /********************************************************************************* + * void addFileToClassPath(String s) + *********************************************************************************/ + public static void addFileToClassPath(String s) throws Exception { + addFileToClassPath(new File(s)); + } + + /********************************************************************************* + * void addFileToClassPath(File f) + *********************************************************************************/ + public static void addFileToClassPath(File f) throws Exception { + addURLToClassPath((f.toURI()).toURL()); + } + + /********************************************************************************* + * void addURLToClassPath(URL url) + *********************************************************************************/ + public static void addURLToClassPath(URL url) throws Exception { + System.out.println("addURLToClassPath-> " + url.toString()); + URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader + .getSystemClassLoader(); + try { + Class urlClassLoaderClass = URLClassLoader.class; + Method method = urlClassLoaderClass.getDeclaredMethod("addURL", + new Class[] { URL.class }); + method.setAccessible(true); + method.invoke(urlClassLoader, new Object[] { url }); + } catch (Throwable t) { + t.printStackTrace(); + throw new IOException("Error, could not add URL to system classloader"); + } + } + + /********************************************************************************* + * JsonArray buildJsonArrayFooBar + *********************************************************************************/ + public static JsonArray buildJsonArrayFooBar() { + try { + JsonArray jsonArray = Json.createArrayBuilder().add("foo").add("bar") + .build(); + return jsonArray; + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + return null; + } + } + + public static final String JSONARRAYFOOBAR = "[\"foo\",\"bar\"]"; + + /********************************************************************************* + * JsonObject buildJsonObjectFooBar() + *********************************************************************************/ + public static JsonObject buildJsonObjectFooBar() { + try { + JsonObject jsonObject = Json.createObjectBuilder().add("foo", "bar") + .build(); + return jsonObject; + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + return null; + } + } + + public static final String JSONOBJECTFOOBAR = "{\"foo\":\"bar\"}"; + + /********************************************************************************* + * JsonObject createSampleJsonObject() + * + * Assertion ids covered: 400/401/403/404/406/408/409 + *********************************************************************************/ + public static JsonObject createSampleJsonObject() throws Exception { + JsonObject object = Json.createObjectBuilder().add("firstName", "John") + .add("lastName", "Smith").add("age", 25).add("elderly", JsonValue.FALSE) + .add("patriot", JsonValue.TRUE) + .add("address", + Json.createObjectBuilder().add("streetAddress", "21 2nd Street") + .add("city", "New York").add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", + Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder().add("type", "cell") + .add("number", "646 555-4567"))) + .add("objectOfFooBar", + Json.createObjectBuilder() + .add("objectFooBar", buildJsonObjectFooBar()) + .add("arrayFooBar", buildJsonArrayFooBar())) + .add("arrayOfFooBar", Json.createArrayBuilder() + .add(buildJsonObjectFooBar()).add(buildJsonArrayFooBar())) + .build(); + return object; + } + + /********************************************************************************* + * EXPECTED_SAMPLEJSONOBJECT_TEXT Constant defining expected Json text output + * of above sample JsonObject + *********************************************************************************/ + public final static String EXPECTED_SAMPLEJSONOBJECT_TEXT = "{\"firstName\":\"John\",\"lastName\":\"Smith\",\"age\":25,\"elderly\":false,\"patriot\":true," + + "\"address\":{\"streetAddress\":\"21 2nd Street\",\"city\":\"New York\",\"state\":\"NY\"," + + "\"postalCode\":\"10021\"},\"phoneNumber\":[{\"type\":\"home\",\"number\":\"212 555-1234\"}," + + "{\"type\":\"cell\",\"number\":\"646 555-4567\"}],\"objectOfFooBar\":{\"objectFooBar\":" + + "{\"foo\":\"bar\"},\"arrayFooBar\":[\"foo\",\"bar\"]},\"arrayOfFooBar\":[{\"foo\":\"bar\"}," + + "[\"foo\",\"bar\"]]}"; + + /********************************************************************************* + * JsonObject createSampleJsonObject2() + *********************************************************************************/ + public static JsonObject createSampleJsonObject2() throws Exception { + JsonObject object = Json.createObjectBuilder().add("firstName", "John") + .add("lastName", "Smith").add("age", 25).add("elderly", JsonValue.FALSE) + .add("patriot", JsonValue.TRUE) + .add("address", + Json.createObjectBuilder().add("streetAddress", "21 2nd Street") + .add("city", "New York").add("state", "NY") + .add("postalCode", "10021")) + .add("phoneNumber", + Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("type", "home") + .add("number", "212 555-1234")) + .add(Json.createObjectBuilder().add("type", "cell") + .add("number", "535 444-1234"))) + .build(); + return object; + } + + /********************************************************************************* + * JsonArray createSampleJsonArray() + * + * Assertion ids covered: 400/401/402/403/404/406/409 + *********************************************************************************/ + public static JsonArray createSampleJsonArray() throws Exception { // Indices + JsonArray array = Json.createArrayBuilder().add(Json.createObjectBuilder() // 0 + .add("name1", "value1").add("name2", "value2")).add(JsonValue.TRUE) + .add(JsonValue.FALSE).add(JsonValue.NULL) // 1,2,3 + .add(100).add(200L).add("string") // 4,5,6 + .add(BigDecimal.valueOf(123456789)).add(new BigInteger("123456789"))// 7,8 + .add(Json.createObjectBuilder() // 9 + .add("name3", "value3").add("name4", "value4")) + .add(true).add(false).addNull() // 10,11,12 + .add(Json.createArrayBuilder() // 13 + .add(2).add(4)) + .add(Json.createObjectBuilder() // 14 + .add("objectFooBar", buildJsonObjectFooBar()) + .add("arrayFooBar", buildJsonArrayFooBar())) + .add(Json.createArrayBuilder() // 15 + .add(buildJsonObjectFooBar()).add(buildJsonArrayFooBar())) + .build(); + return array; + } + + /********************************************************************************* + * EXPECTED_SAMPLEJSONARRAY_TEXT Constant defining expected Json text output + * of above sample JsonArray + *********************************************************************************/ + public final static String EXPECTED_SAMPLEJSONARRAY_TEXT = "[{\"name1\":\"value1\",\"name2\":\"value2\"},true,false,null,100,200,\"string\",123456789,123456789," + + "{\"name3\":\"value3\",\"name4\":\"value4\"},true,false,null,[2,4],{\"objectFooBar\":" + + "{\"foo\":\"bar\"},\"arrayFooBar\":[\"foo\",\"bar\"]},[{\"foo\":\"bar\"},[\"foo\",\"bar\"]]]"; + + /********************************************************************************* + * JsonArray createSampleJsonArray2() + *********************************************************************************/ + public static JsonArray createSampleJsonArray2() throws Exception { // Indices + JsonArray array = Json.createArrayBuilder().add(Json.createObjectBuilder() // 0 + .add("name1", "value1").add("name2", "value2")).add(JsonValue.TRUE) + .add(JsonValue.FALSE).add(JsonValue.NULL) // 1,2,3 + .add(Integer.MAX_VALUE).add(Long.MAX_VALUE).add("string") // 4,5,6 + .add(Json.createObjectBuilder() // 7 + .add("name3", "value3").add("name4", "value4")) + .add(true).add(false).addNull() // 8,9,10 + .add(Json.createArrayBuilder() // 11 + .add(1).add(3)) + .build(); + return array; + } +}
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyBufferedInputStream.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyBufferedInputStream.java new file mode 100644 index 0000000..7e59aaf --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyBufferedInputStream.java
@@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.common; + + +import java.io.*; + +// A wrapper class to BufferedInputStream class used to inject IOException errors +// when the throwIOException instance variable is set. All methods delegate +// to the parent super class and check whether or not to throw an IOException +// before delegation. + +public class MyBufferedInputStream extends BufferedInputStream { + + private boolean throwIOException = false; + + public MyBufferedInputStream(InputStream in) { + super(in); + } + + public MyBufferedInputStream(InputStream in, int sz) { + super(in, sz); + } + + public MyBufferedInputStream(InputStream in, boolean throwIOException) { + super(in); + this.throwIOException = throwIOException; + } + + private void checkToTripIOException() throws IOException { + if (throwIOException) { + System.out.println( + "MyBufferedInputStream->checkToTripIOException: *** tripping an IOException ***"); + throw new IOException("tripping an IOException"); + } + } + + public void setThrowIOException(boolean throwIOException) { + this.throwIOException = throwIOException; + } + + public int read() throws IOException { + checkToTripIOException(); + int c = super.read(); + return c; + } + + public int read(byte[] b, int off, int len) throws IOException { + checkToTripIOException(); + int c = super.read(b, off, len); + return c; + } + + public void close() throws IOException { + checkToTripIOException(); + super.close(); + } +}
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyBufferedReader.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyBufferedReader.java new file mode 100644 index 0000000..00c5145 --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyBufferedReader.java
@@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.common; + + +import java.io.*; + +// A wrapper class to BufferedReader class used to inject IOException errors +// when the throwIOException instance variable is set. All methods delegate +// to the parent super class and check whether or not to throw an IOException +// before delegation. + +public class MyBufferedReader extends BufferedReader { + + private boolean throwIOException; + + public MyBufferedReader(Reader in) { + super(in); + } + + public MyBufferedReader(Reader in, int sz) { + super(in, sz); + } + + public MyBufferedReader(Reader in, int sz, boolean throwIOException) { + super(in, sz); + this.throwIOException = throwIOException; + } + + private void checkToTripIOException() throws IOException { + if (throwIOException) { + System.out.println("*** tripping an IOException ***"); + throw new IOException("tripping an IOException"); + } + } + + public void setThrowIOException(boolean throwIOException) { + this.throwIOException = throwIOException; + } + + public int read() throws IOException { + checkToTripIOException(); + return super.read(); + } + + public int read(char[] cbuf, int off, int len) throws IOException { + checkToTripIOException(); + return super.read(cbuf, off, len); + } + + public String readLine() throws IOException { + checkToTripIOException(); + return super.readLine(); + } + + public boolean ready() throws IOException { + checkToTripIOException(); + return super.ready(); + } + + public void reset() throws IOException { + checkToTripIOException(); + super.reset(); + } + + public void close() throws IOException { + checkToTripIOException(); + super.close(); + } +}
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyBufferedWriter.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyBufferedWriter.java new file mode 100644 index 0000000..a06c99a --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyBufferedWriter.java
@@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.common; + + +import java.io.*; + +// A wrapper class to BufferedWriter class used to inject IOException errors +// when the throwIOException instance variable is set. All methods delegate +// to the parent super class and check whether or not to throw an IOException +// before delegation. + +public class MyBufferedWriter extends BufferedWriter { + + private boolean throwIOException; + + public MyBufferedWriter(Writer out) { + super(out); + } + + public MyBufferedWriter(Writer out, int sz) { + super(out, sz); + } + + public MyBufferedWriter(Writer out, int sz, boolean throwIOException) { + super(out, sz); + this.throwIOException = throwIOException; + } + + private void checkToTripIOException() throws IOException { + if (throwIOException) { + System.out.println("*** tripping an IOException ***"); + throw new IOException("tripping an IOException"); + } + } + + public void setThrowIOException(boolean throwIOException) { + this.throwIOException = throwIOException; + } + + public void write(int c) throws IOException { + checkToTripIOException(); + super.write(c); + } + + public void write(char[] cbuf) throws IOException { + checkToTripIOException(); + super.write(cbuf); + } + + public void write(char[] cbuf, int offset, int length) throws IOException { + checkToTripIOException(); + super.write(cbuf, offset, length); + } + + public void write(String str) throws IOException { + checkToTripIOException(); + super.write(str); + } + + public void write(String str, int offset, int length) throws IOException { + checkToTripIOException(); + super.write(str, offset, length); + } + + public void close() throws IOException { + checkToTripIOException(); + super.close(); + } + + public void flush() throws IOException { + checkToTripIOException(); + super.flush(); + } +}
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyJsonLocation.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyJsonLocation.java new file mode 100644 index 0000000..4882ac7 --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/common/MyJsonLocation.java
@@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.common; + + +import jakarta.json.stream.JsonLocation; + +public class MyJsonLocation implements JsonLocation { + + private long lineNumber = -1; + + private long columnNumber = -1; + + private long streamOffset = -1; + + public MyJsonLocation() { + } + + public MyJsonLocation(long lineNumber, long columnNumber, long streamOffset) { + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + this.streamOffset = streamOffset; + } + + public void setLineNumber(long lineNumber) { + this.lineNumber = lineNumber; + } + + public long getLineNumber() { + return lineNumber; + } + + public void setColumnNumber(long columnNumber) { + this.columnNumber = columnNumber; + } + + public long getColumnNumber() { + return columnNumber; + } + + public void setStreamOffset(long streamOffset) { + this.streamOffset = streamOffset; + } + + public long getStreamOffset() { + return streamOffset; + } +}
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/lib/harness/Fault.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/lib/harness/Fault.java new file mode 100644 index 0000000..b7a83e0 --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/lib/harness/Fault.java
@@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.lib.harness; + +import junit.framework.AssertionFailedError; + +public class Fault extends AssertionFailedError { + + private static final long serialVersionUID = 1L; + + public Fault() { + super(); + } + + public Fault(String message) { + super(message); + } + + public Fault(String message, Throwable cause) { + super(message + cause); + } + +}
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/util/FileUTFConverter.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/util/FileUTFConverter.java new file mode 100644 index 0000000..fe03252 --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/util/FileUTFConverter.java
@@ -0,0 +1,111 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +/* + * Usage: java FileUTFConverter [-toUTF|-fromUTF] encoding infile outfile + * + * Utility program for converting a UTF-8 file to various UTF + * encoded files and vice-versa. + * + * Example(s): + * + * java FileUTFConverter -toUTF UTF-16 jsonObjectUTF8.json jsonObjectUTF16.json + * + * The above takes a UTF-8 encoded input file (jsonObjectUTF8.json) and converts + * it to a UTF-16 encoded output file (jsonObjectUTF16.json). + * + * java FileUTFConverter -fromUTF UTF-16 jsonObjectUTF16.json jsonObjectUTF8.json + * + * The above takes a UTF-16 encoded input file (jsonObjectUTF16.json) and + * converts it to a UTF-8 encoded output file (jsonObjectUTF8.json). + * + * All UTF encodings can be used: + * + * UTF-8 + * UTF-16 + * UTF-16BE + * UTF-16LE + * UTF-32BE + * UTF-32LE + */ + +package jakarta.jsonp.tck.util; + +import java.io.*; + +public class FileUTFConverter { + + private static final String USAGE = "Usage : java FileUTFConverter [-toUTF|-fromUTF] encoding infile outfile"; + + public static void main(String args[]) { + try { + if (args.length != 4) { + System.err.println(USAGE); + System.exit(1); + } + + // Convert UTF-8 input file to specified UTF encoded output file + if (args[0].equals("-toUTF")) { + System.out + .println("FileUTFConverter-> convert UTF-8 encoded input file (" + + args[2] + "), to encoding (" + args[1] + + ") and write to output file (" + args[3] + ")"); + FileInputStream fis = new FileInputStream(args[2]); + BufferedReader br = new BufferedReader( + new InputStreamReader(fis, "UTF-8")); + FileOutputStream fos = new FileOutputStream(args[3]); + BufferedWriter bw = new BufferedWriter( + new OutputStreamWriter(fos, args[1])); + for (String s = ""; (s = br.readLine()) != null;) { + bw.write(s + System.getProperty("line.separator")); + bw.flush(); + } + bw.close(); + br.close(); + // Convert specified UTF encoded input file to UTF-8 encoded output file + } else if (args[0].equals("-fromUTF")) { + System.out.println("FileUTFConverter-> convert UTF encoded input file (" + + args[2] + "), from encoding (" + args[1] + + ") and write to UTF-8 encoded output file (" + args[3] + ")"); + FileInputStream fis = new FileInputStream(args[2]); + BufferedReader br = new BufferedReader( + new InputStreamReader(fis, args[1])); + FileOutputStream fos = new FileOutputStream(args[3]); + BufferedWriter bw = new BufferedWriter( + new OutputStreamWriter(fos, "UTF-8")); + for (String s = ""; (s = br.readLine()) != null;) { + bw.write(s + System.getProperty("line.separator")); + bw.flush(); + } + bw.close(); + br.close(); + } else { + System.err.println(USAGE); + System.exit(1); + } + + System.exit(0); + + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + } +}
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/util/MyEncoder.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/util/MyEncoder.java new file mode 100644 index 0000000..4ab6483 --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/util/MyEncoder.java
@@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.util; + +import java.io.*; + +/* + * Used to generate an encoded file preceded by N null characters. + * + * This utility takes a valid Json text file as input and generates + * an encoded version as output file with N null characters preceded by + * each character. For empty files it will just output the N null chars. + * + */ +public class MyEncoder { + + private static final int NULL = '\0'; + + private static final String USAGE = "Usage : java MyEncoder #nulls infile outfile"; + + public static void main(String args[]) { + if (args.length != 3) { + System.err.println(USAGE); + System.exit(1); + } + + FileReader inputStream = null; + FileWriter outputStream = null; + + try { + int n = Integer.parseInt(args[0]); + inputStream = new FileReader(args[1]); + outputStream = new FileWriter(args[2]); + + System.out.println("Null chars: " + args[0]); + System.out.println("Input file: " + args[1]); + System.out.println("Output file: " + args[2]); + + System.out + .println("\nCreating an encoded file with each char preceded by " + n + + " null chars.\n"); + + int c; + int nchars = 0; + while ((c = inputStream.read()) != -1) { + nchars++; + for (int i = 0; i < n; i++) + outputStream.write(NULL); + outputStream.write(c); + } + if (nchars == 0) { + for (int i = 0; i < n; i++) + outputStream.write(NULL); // if empty file at least write the nulls + // out + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (Exception e) { + } + } + if (outputStream != null) { + try { + outputStream.close(); + } catch (Exception e) { + } + } + } + System.exit(0); + } +}
diff --git a/tck/tck-common/src/main/java/jakarta/jsonp/tck/util/StringUTFConverter.java b/tck/tck-common/src/main/java/jakarta/jsonp/tck/util/StringUTFConverter.java new file mode 100644 index 0000000..cefd268 --- /dev/null +++ b/tck/tck-common/src/main/java/jakarta/jsonp/tck/util/StringUTFConverter.java
@@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +/* + * Usage: java StringUTFConverter inputstring encoding outputfile + * + * Utility program to convert an input string to a UTF encoded output file. + * + * Example(s): + * + * java StringUTFConverter "foo" UTF-16LE fooUTF16LE + * + * The above converts an input string "foo" and outputs to UTF-16LE encoded + * output file (fooUTF16LE). + */ + +package jakarta.jsonp.tck.util; + +import java.io.*; + +public class StringUTFConverter { + + private static final String USAGE = "Usage : java StringUTFConverter inputstring encoding outputfile"; + + public static void main(String args[]) { + try { + if (args.length != 3) { + System.err.println(USAGE); + System.exit(1); + } + + // Convert string to specified UTF encoded output file + System.out.println( + "StringtoUTF-> convert string (" + args[0] + "), to encoding (" + + args[1] + ") and write to output file (" + args[2] + ")"); + FileOutputStream fos = new FileOutputStream(args[2]); + BufferedWriter bw = new BufferedWriter( + new OutputStreamWriter(fos, args[1])); + bw.write(args[0]); + bw.flush(); + bw.close(); + + System.exit(0); + + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + } +}
diff --git a/tck/tck-tests-plugability/pom.xml b/tck/tck-tests-plugability/pom.xml new file mode 100644 index 0000000..9ffbf88 --- /dev/null +++ b/tck/tck-tests-plugability/pom.xml
@@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck</artifactId> + <version>2.0.0-SNAPSHOT</version> + </parent> + + <artifactId>jakarta.json-tck-tests-plugability</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck-common</artifactId> + <version>2.0.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + </dependencies> + +</project>
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/pluggability/jsonprovidertests/ClientTests.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/pluggability/jsonprovidertests/ClientTests.java new file mode 100644 index 0000000..58310ed --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/pluggability/jsonprovidertests/ClientTests.java
@@ -0,0 +1,554 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.pluggability.jsonprovidertests; + +import jakarta.json.*; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.*; + +import java.io.*; +import java.nio.charset.Charset; + +import java.util.Properties; +import java.util.ServiceLoader; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; + +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; +import jakarta.jsonp.tck.provider.MyJsonProvider; +import jakarta.jsonp.tck.provider.MyJsonGenerator; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + + private static final String MY_JSONPROVIDER_CLASS = "jakarta.jsonp.tck.provider.MyJsonProvider"; + + private String providerPath = null; + + @After + public void after() { + MyJsonProvider.clearCalls(); + MyJsonGenerator.clearCalls(); + } + + /* Tests */ + + /* + * @testName: jsonProviderTest1 + * + * @assertion_ids: JSONP:JAVADOC:152; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * static JsonProvider provider() + */ + @Test + public void jsonProviderTest1() throws Fault { + boolean pass = true; + try { + // Load my provider + JsonProvider provider = JsonProvider.provider(); + String providerClass = provider.getClass().getName(); + System.out.println("provider class=" + providerClass); + if (providerClass.equals(MY_JSONPROVIDER_CLASS)) + System.out.println("Current provider is my provider - expected."); + else { + System.err.println("Current provider is not my provider - unexpected."); + pass = false; + ServiceLoader<JsonProvider> loader = ServiceLoader.load(JsonProvider.class); + Iterator<JsonProvider> it = loader.iterator(); + List<JsonProvider> providers = new ArrayList<>(); + while(it.hasNext()) { + providers.add(it.next()); + } + System.out.println("Providers: "+providers); + } + } catch (Exception e) { + throw new Fault("jsonProviderTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest1 Failed"); + } + + /* + * @testName: jsonProviderTest2 + * + * @assertion_ids: JSONP:JAVADOC:144; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonGenerator createGenerator(Writer) + */ + @Test + public void jsonProviderTest2() throws Fault { + boolean pass = true; + String expString = "public JsonGenerator createGenerator(Writer)"; + String expString2 = "public JsonGenerator writeStartArray()"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonGenerator generator = Json.createGenerator(new StringWriter()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + generator.writeStartArray(); + String actString2 = MyJsonGenerator.getCalls(); + System.out.println("Verify SPI generator method was called: " + expString2); + pass = JSONP_Util.assertEquals(expString2, actString2); + } catch (Exception e) { + throw new Fault("jsonProviderTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest2 Failed"); + } + + /* + * @testName: jsonProviderTest3 + * + * @assertion_ids: JSONP:JAVADOC:192; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonGenerator createGenerator(OutputStream) + */ + @Test + public void jsonProviderTest3() throws Fault { + boolean pass = true; + String expString = "public JsonGenerator createGenerator(OutputStream)"; + String expString2 = "public JsonGenerator writeStartObject()"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonGenerator generator = Json + .createGenerator(new ByteArrayOutputStream()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + generator.writeStartObject(); + String actString2 = MyJsonGenerator.getCalls(); + System.out.println("Verify SPI generator method was called: " + expString2); + pass = JSONP_Util.assertEquals(expString2, actString2); + } catch (Exception e) { + throw new Fault("jsonProviderTest3 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest3 Failed"); + } + + /* + * @testName: jsonProviderTest4 + * + * @assertion_ids: JSONP:JAVADOC:146; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonParser createParser(Reader) + */ + @Test + public void jsonProviderTest4() throws Fault { + boolean pass = true; + String expString = "public JsonParser createParser(Reader)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonParser parser = Json.createParser(new StringReader("{}")); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest4 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest4 Failed"); + } + + /* + * @testName: jsonProviderTest5 + * + * @assertion_ids: JSONP:JAVADOC:196; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonParser createParser(InputStream) + */ + @Test + public void jsonProviderTest5() throws Fault { + boolean pass = true; + String expString = "public JsonParser createParser(InputStream)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonParser parser = Json + .createParser(JSONP_Util.getInputStreamFromString("{}")); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest5 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest5 Failed"); + } + + /* + * @testName: jsonProviderTest6 + * + * @assertion_ids: JSONP:JAVADOC:465; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonParserFactory createParserFactory(Map<String, ?>) + */ + @Test + public void jsonProviderTest6() throws Fault { + boolean pass = true; + String expString = "public JsonParserFactory createParserFactory(Map<String, ?>)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonParserFactory parserFactory = Json + .createParserFactory(JSONP_Util.getEmptyConfig()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest6 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest6 Failed"); + } + + /* + * @testName: jsonProviderTest7 + * + * @assertion_ids: JSONP:JAVADOC:426; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonParserFactory createParserFactory(Map<String, ?>) + */ + @Test + public void jsonProviderTest7() throws Fault { + boolean pass = true; + String expString = "public JsonParserFactory createParserFactory(Map<String, ?>)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonParserFactory parserFactory = Json + .createParserFactory(new HashMap<String, Object>()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest7 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest7 Failed"); + } + + /* + * @testName: jsonProviderTest8 + * + * @assertion_ids: JSONP:JAVADOC:425; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonGeneratorFactory createGeneratorFactory(Map<String, ?>) + */ + @Test + public void jsonProviderTest8() throws Fault { + boolean pass = true; + String expString = "public JsonGeneratorFactory createGeneratorFactory(Map<String, ?>)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonGeneratorFactory generatorFactory = Json + .createGeneratorFactory(new HashMap<String, Object>()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest8 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest8 Failed"); + } + + /* + * @testName: jsonProviderTest9 + * + * @assertion_ids: JSONP:JAVADOC:472; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonWriterFactory createWriterFactory(Map<String, ?>) + */ + @Test + public void jsonProviderTest9() throws Fault { + boolean pass = true; + String expString = "public JsonWriterFactory createWriterFactory(Map<String, ?>)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonWriterFactory factory = Json + .createWriterFactory(JSONP_Util.getEmptyConfig()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest9 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest9 Failed"); + } + + /* + * @testName: jsonProviderTest10 + * + * @assertion_ids: JSONP:JAVADOC:223; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonParser createParser(InputStream) Tests the case where a JsonException + * can be thrown. An InputStream of null will cause MyJsonProvider to throw + * JsonException. + */ + @Test + public void jsonProviderTest10() throws Fault { + boolean pass = true; + String expString = "public JsonParser createParser(InputStream)"; + try { + System.out.println("Calling SPI provider method: " + expString); + InputStream in = null; + JsonParser parser = Json.createParser(in); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException: " + e); + } catch (Exception e) { + throw new Fault("jsonProviderTest10 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest10 Failed"); + } + + /* + * @testName: jsonProviderTest11 + * + * @assertion_ids: JSONP:JAVADOC:464; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonArrayBuilder createArrayBuilder() + */ + @Test + public void jsonProviderTest11() throws Fault { + boolean pass = true; + String expString = "public JsonArrayBuilder createArrayBuilder()"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest11 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest11 Failed"); + } + + /* + * @testName: jsonProviderTest12 + * + * @assertion_ids: JSONP:JAVADOC:466; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonObjectBuilder createObjectBuilder() + */ + @Test + public void jsonProviderTest12() throws Fault { + boolean pass = true; + String expString = "public JsonObjectBuilder createObjectBuilder()"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonObjectBuilder objectBuilder = Json.createObjectBuilder(); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest12 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest12 Failed"); + } + + /* + * @testName: jsonProviderTest13 + * + * @assertion_ids: JSONP:JAVADOC:465; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonBuilderFactory createBuilderFactory(Map<String, ?>) + */ + @Test + public void jsonProviderTest13() throws Fault { + boolean pass = true; + String expString = "public JsonBuilderFactory createBuilderFactory(Map<String, ?>)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonBuilderFactory objectBuilder = Json + .createBuilderFactory(JSONP_Util.getEmptyConfig()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest13 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest13 Failed"); + } + + /* + * @testName: jsonProviderTest14 + * + * @assertion_ids: JSONP:JAVADOC:467; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonReader createReader(Reader) + */ + @Test + public void jsonProviderTest14() throws Fault { + boolean pass = true; + String expString = "public JsonReader createReader(Reader)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonReader reader = Json.createReader(new StringReader("{}")); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest14 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest14 Failed"); + } + + /* + * @testName: jsonProviderTest15 + * + * @assertion_ids: JSONP:JAVADOC:468; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonReader createReader(InputStream) + */ + @Test + public void jsonProviderTest15() throws Fault { + boolean pass = true; + String expString = "public JsonReader createReader(InputStream)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonReader reader = Json + .createReader(JSONP_Util.getInputStreamFromString("{}")); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest15 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest15 Failed"); + } + + /* + * @testName: jsonProviderTest16 + * + * @assertion_ids: JSONP:JAVADOC:470; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonWriter createWriter(Writer) + */ + @Test + public void jsonProviderTest16() throws Fault { + boolean pass = true; + String expString = "public JsonWriter createWriter(Writer)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonWriter writer = Json.createWriter(new StringWriter()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest16 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest16 Failed"); + } + + /* + * @testName: jsonProviderTest17 + * + * @assertion_ids: JSONP:JAVADOC:471; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonWriter createWriter(OutputStream) + */ + @Test + public void jsonProviderTest17() throws Fault { + boolean pass = true; + String expString = "public JsonWriter createWriter(OutputStream)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonWriter writer = Json.createWriter(new ByteArrayOutputStream()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest17 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest17 Failed"); + } + + /* + * @testName: jsonProviderTest18 + * + * @assertion_ids: JSONP:JAVADOC:469; + * + * @test_Strategy: Test call of SPI provider method with signature: o public + * JsonReaderFactory createReaderFactory(Map<String, ?>) + */ + @Test + public void jsonProviderTest18() throws Fault { + boolean pass = true; + String expString = "public JsonReaderFactory createReaderFactory(Map<String, ?>)"; + try { + System.out.println("Calling SPI provider method: " + expString); + JsonReaderFactory factory = Json + .createReaderFactory(JSONP_Util.getEmptyConfig()); + String actString = MyJsonProvider.getCalls(); + System.out.println("Verify SPI provider method was called: " + expString); + pass = JSONP_Util.assertEquals(expString, actString); + } catch (Exception e) { + throw new Fault("jsonProviderTest18 Failed: ", e); + } + if (!pass) + throw new Fault("jsonProviderTest18 Failed"); + } +}
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonGenerator.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonGenerator.java new file mode 100644 index 0000000..9340070 --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonGenerator.java
@@ -0,0 +1,252 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.provider; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.charset.Charset; +import jakarta.json.*; +import jakarta.json.stream.*; + +/* + * MyJsonGenerator is a Json Test Generator used by the pluggability tests + * to test the Json SPI layer. This generator tracks that the proper callback + * methods are invoked within the generator when Json API methods are called. + */ + +public class MyJsonGenerator implements JsonGenerator { + private Writer writer = null; + + private OutputStream out = null; + + private final Charset charset = Charset.forName("UTF-8"); + + private void dumpInstanceVars() { + System.out.println("writer=" + writer); + System.out.println("out=" + out); + System.out.println("charset=" + charset); + } + + // call methods + private static StringBuilder calls = new StringBuilder(); + + public static String getCalls() { + return calls.toString(); + } + + public static void clearCalls() { + calls.delete(0, calls.length()); + } + + private static void addCalls(String s) { + calls.append(s); + } + + public MyJsonGenerator(Writer writer) { + this.writer = writer; + } + + public MyJsonGenerator(OutputStream out) { + this.out = out; + } + + @Override + public void flush() { + System.out.println("public void flush()"); + addCalls("public void flush()"); + } + + @Override + public JsonGenerator writeStartObject() { + System.out.println("public JsonGenerator writeStartObject()"); + addCalls("public JsonGenerator writeStartObject()"); + return null; + } + + @Override + public JsonGenerator writeStartObject(String name) { + System.out.println("public JsonGenerator writeStartObject(String)"); + addCalls("public JsonGenerator writeStartObject(String)"); + return null; + } + + @Override + public JsonGenerator write(String name, String value) { + System.out.println("public JsonGenerator write(String,String)"); + addCalls("public JsonGenerator write(String,String)"); + return null; + } + + @Override + public JsonGenerator write(String name, int value) { + System.out.println("public JsonGenerator write(String,int)"); + addCalls("public JsonGenerator write(String,int)"); + return null; + } + + @Override + public JsonGenerator write(String name, long value) { + System.out.println("public JsonGenerator write(String,long)"); + addCalls("public JsonGenerator write(String,long)"); + return null; + } + + @Override + public JsonGenerator write(String name, double value) { + System.out.println("public JsonGenerator write(String,double)"); + addCalls("public JsonGenerator write(String,double)"); + return null; + } + + @Override + public JsonGenerator write(String name, BigInteger value) { + System.out.println("public JsonGenerator write(String,BigInteger)"); + addCalls("public JsonGenerator write(String,BigInteger)"); + return null; + } + + @Override + public JsonGenerator write(String name, BigDecimal value) { + System.out.println("public JsonGenerator write(String,BigDecimal)"); + addCalls("public JsonGenerator write(String,BigDecimal)"); + return null; + } + + @Override + public JsonGenerator write(String name, boolean value) { + System.out.println("public JsonGenerator write(String,boolean)"); + addCalls("public JsonGenerator write(String,boolean)"); + return null; + } + + @Override + public JsonGenerator write(String name, JsonValue value) { + System.out.println("public JsonGenerator write(String,JsonValue)"); + addCalls("public JsonGenerator write(String,JsonValue)"); + return null; + } + + @Override + public JsonGenerator writeNull(String name) { + System.out.println("public JsonGenerator writeNull(String)"); + addCalls("public JsonGenerator writeNull(String)"); + return null; + } + + @Override + public JsonGenerator writeStartArray() { + System.out.println("public JsonGenerator writeStartArray()"); + addCalls("public JsonGenerator writeStartArray()"); + return null; + } + + @Override + public JsonGenerator writeStartArray(String name) { + System.out.println("public JsonGenerator writeStartArray(String)"); + addCalls("public JsonGenerator writeStartArray(String)"); + return null; + } + + @Override + public JsonGenerator write(String value) { + System.out.println("public JsonGenerator write(String)"); + addCalls("public JsonGenerator write(String)"); + return null; + } + + @Override + public JsonGenerator write(int value) { + System.out.println("public JsonGenerator write(int)"); + addCalls("public JsonGenerator write(int)"); + return null; + } + + @Override + public JsonGenerator write(long value) { + System.out.println("public JsonGenerator write(long)"); + addCalls("public JsonGenerator write(long)"); + return null; + } + + @Override + public JsonGenerator write(double value) { + System.out.println("public JsonGenerator write(double)"); + addCalls("public JsonGenerator write(double)"); + return null; + } + + @Override + public JsonGenerator write(BigInteger value) { + System.out.println("public JsonGenerator write(BigInteger)"); + addCalls("public JsonGenerator write(BigInteger)"); + return null; + } + + @Override + public JsonGenerator write(BigDecimal value) { + System.out.println("public JsonGenerator write(BigDecimal)"); + addCalls("public JsonGenerator write(BigDecimal)"); + return null; + } + + @Override + public JsonGenerator write(boolean value) { + System.out.println("public JsonGenerator write(boolean)"); + addCalls("public JsonGenerator write(boolean)"); + return null; + } + + @Override + public JsonGenerator write(JsonValue value) { + System.out.println("public JsonGenerator write(JsonValue)"); + addCalls("public JsonGenerator write(JsonValue)"); + return null; + } + + @Override + public JsonGenerator writeNull() { + System.out.println("public JsonGenerator writeNull()"); + addCalls("public JsonGenerator writeNull()"); + return null; + } + + @Override + public JsonGenerator writeEnd() { + System.out.println("public JsonGenerator writeEnd()"); + addCalls("public JsonGenerator writeEnd()"); + return null; + } + + @Override + public JsonGenerator writeKey(String name) { + System.out.println("public JsonGenerator writeKey()"); + addCalls("public JsonGenerator writeKey()"); + return null; + } + + @Override + public void close() { + System.out.println("public void close()"); + addCalls("public void close()"); + } + +}
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonGeneratorFactory.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonGeneratorFactory.java new file mode 100644 index 0000000..d5ae3dd --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonGeneratorFactory.java
@@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.provider; + +import jakarta.json.*; +import jakarta.json.stream.*; +import java.io.*; +import java.nio.charset.Charset; +import java.util.*; + +/* + * MyJsonGeneratorFactory is a Json Test GeneratorFactory used by the pluggability tests + * to test the Json SPI layer. This parser tracks that the proper callback + * methods are invoked within the parser when Json API methods are called. + */ + +public class MyJsonGeneratorFactory implements JsonGeneratorFactory { + private OutputStream out = null; + + private Writer writer = null; + + private Charset charset = Charset.forName("UTF-8"); + + private Map<String, ?> config = null; + + private void dumpInstanceVars() { + System.out.println("writer=" + writer); + System.out.println("out=" + out); + System.out.println("charset=" + charset); + System.out.println("config=" + config); + } + + // call methods + private static StringBuilder calls = new StringBuilder(); + + public static String getCalls() { + return calls.toString(); + } + + public static void clearCalls() { + calls.delete(0, calls.length()); + } + + private static void addCalls(String s) { + calls.append(s); + } + + public MyJsonGeneratorFactory(Map<String, ?> config) { + this.config = config; + } + + public Map<String, ?> getConfigInUse() { + System.out.println("public Map<String, ?> getConfigInUse()"); + addCalls("public Map<String, ?> getConfigInUse()"); + return config; + } + + public JsonGenerator createGenerator(OutputStream out) { + System.out.println("public JsonGenerator createGenerator(OutputStream)"); + addCalls("public JsonGenerator createGenerator(OutputStream)"); + this.out = out; + return null; + } + + public JsonGenerator createGenerator(OutputStream out, Charset charset) { + System.out.println( + "public JsonGenerator createGenerator(OutputStream, Charset)"); + addCalls("public JsonGenerator createGenerator(OutputStream, Charset)"); + this.out = out; + this.charset = charset; + return null; + } + + public JsonGenerator createGenerator(Writer writer) { + System.out.println("public JsonGenerator createGenerator(Writer)"); + addCalls("public JsonGenerator createGenerator(Writer)"); + this.writer = writer; + return null; + } +}
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonParser.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonParser.java new file mode 100644 index 0000000..5df3fc5 --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonParser.java
@@ -0,0 +1,124 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.provider; + + +import jakarta.json.*; +import jakarta.json.stream.*; +import jakarta.json.spi.JsonProvider; +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.util.*; + +/* + * MyJsonParser is a Json Test Parser used by the pluggability tests + * to test the Json SPI layer. This parser tracks that the proper callback + * methods are invoked within the parser when Json API methods are called. + */ + +public class MyJsonParser implements JsonParser { + private InputStream in = null; + + private Reader reader = null; + + private void dumpInstanceVars() { + System.out.println("reader=" + reader); + System.out.println("in=" + in); + } + + // call methods + private static StringBuilder calls = new StringBuilder(); + + public static String getCalls() { + return calls.toString(); + } + + public static void clearCalls() { + calls.delete(0, calls.length()); + } + + private static void addCalls(String s) { + calls.append(s); + } + + public MyJsonParser(InputStream in) { + this.in = in; + } + + public MyJsonParser(Reader reader) { + this.reader = reader; + } + + public void close() { + System.out.println("public void close()"); + addCalls("public void close()"); + } + + public BigDecimal getBigDecimal() { + System.out.println("public BigDecimal getBigDecimal()"); + addCalls("public BigDecimal getBigDecimal()"); + return null; + } + + public int getInt() { + System.out.println("public int getInt()"); + addCalls("public int getInt()"); + return -1; + } + + public JsonLocation getLocation() { + System.out.println("public JsonLocation getLocation()"); + addCalls("public JsonLocation getLocation()"); + return null; + } + + public long getLong() { + System.out.println("public long getLong()"); + addCalls("public long getLong()"); + return -1; + } + + public boolean isIntegralNumber() { + System.out.println("public boolean isIntegralNumber()"); + addCalls("public boolean isIntegralNumber()"); + return false; + } + + public String getString() { + System.out.println("public String getString()"); + addCalls("public String getString()"); + return null; + } + + public boolean hasNext() { + System.out.println("public boolean hasNext()"); + addCalls("public boolean hasNext()"); + return false; + } + + public JsonParser.Event next() { + System.out.println("public JsonParser.Event next()"); + addCalls("public JsonParser.Event next()"); + return null; + } +}
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonParserFactory.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonParserFactory.java new file mode 100644 index 0000000..0d06523 --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonParserFactory.java
@@ -0,0 +1,109 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.provider; + +import jakarta.json.*; +import jakarta.json.stream.*; +import java.io.*; +import java.nio.charset.Charset; +import java.util.*; + +/* + * MyJsonParserFactory is a Json Test ParserFactory used by the pluggability tests + * to test the Json SPI layer. This parser tracks that the proper callback + * methods are invoked within the parser when Json API methods are called. + */ + +public class MyJsonParserFactory implements JsonParserFactory { + private InputStream in = null; + + private Charset charset = null; + + private Reader reader = null; + + private Map<String, ?> config = null; + + private void dumpInstanceVars() { + System.out.println("reader=" + reader); + System.out.println("in=" + in); + System.out.println("charset=" + charset); + System.out.println("config=" + config); + } + + // call methods + private static StringBuilder calls = new StringBuilder(); + + public static String getCalls() { + return calls.toString(); + } + + public static void clearCalls() { + calls.delete(0, calls.length()); + } + + private static void addCalls(String s) { + calls.append(s); + } + + public MyJsonParserFactory(Map<String, ?> config) { + this.config = config; + } + + public Map<String, ?> getConfigInUse() { + System.out.println("public Map<String, ?> getConfigInUse()"); + addCalls("public Map<String, ?> getConfigInUse()"); + return config; + } + + public JsonParser createParser(InputStream in) { + System.out.println("public JsonParser createParser(InputStream)"); + addCalls("public JsonParser createParser(InputStream)"); + this.in = in; + return null; + } + + public JsonParser createParser(InputStream in, Charset charset) { + System.out.println("public JsonParser createParser(InputStream, Charset)"); + addCalls("public JsonParser createParser(InputStream, Charset)"); + this.in = in; + this.charset = charset; + return null; + } + + public JsonParser createParser(Reader reader) { + System.out.println("public JsonParser createParser(Reader)"); + addCalls("public JsonParser createParser(Reader)"); + this.reader = reader; + return null; + } + + public JsonParser createParser(JsonArray jsonArray) { + System.out.println("public JsonParser createParser(JsonArray)"); + addCalls("public JsonParser createParser(JsonArray)"); + return null; + } + + public JsonParser createParser(JsonObject jsonObject) { + System.out.println("public JsonParser createParser(JsonObject)"); + addCalls("public JsonParser createParser(JsonObject)"); + return null; + } +}
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonProvider.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonProvider.java new file mode 100644 index 0000000..c7d1680 --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonProvider.java
@@ -0,0 +1,188 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.provider; + +import java.io.*; +import java.util.*; +import jakarta.json.*; +import jakarta.json.spi.JsonProvider; +import jakarta.json.stream.*; + +// $Id$ +/* + * MyJsonProvider is a Json Test Provider used by the pluggability tests + * to test the Json SPI layer. This provider tracks that the proper callback + * methods are invoked within the provider when Json API methods are called. + */ +public class MyJsonProvider extends JsonProvider { + + // Exception thrown when encoding or i/o error + private final JsonException exception = new JsonException( + "encoding or i/o error"); + + // call methods + private static final StringBuilder CALLS = new StringBuilder(); + + public static String getCalls() { + return CALLS.toString(); + } + + public static void clearCalls() { + CALLS.delete(0, CALLS.length()); + } + + private static void addCalls(String s) { + CALLS.append(s); + } + + @Override + public JsonArrayBuilder createArrayBuilder() { + System.out.println("public JsonArrayBuilder createArrayBuilder()"); + addCalls("public JsonArrayBuilder createArrayBuilder()"); + return null; + } + + @Override + public JsonBuilderFactory createBuilderFactory(Map<String, ?> config) { + System.out.println( + "public JsonBuilderFactory createBuilderFactory(Map<String, ?>)"); + addCalls("public JsonBuilderFactory createBuilderFactory(Map<String, ?>)"); + return null; + } + + @Override + public JsonObjectBuilder createObjectBuilder() { + System.out.println("public JsonObjectBuilder createObjectBuilder()"); + addCalls("public JsonObjectBuilder createObjectBuilder()"); + return null; + } + + @Override + public JsonReader createReader(Reader reader) { + System.out.println("public JsonReader createReader(Reader)"); + addCalls("public JsonReader createReader(Reader)"); + return new MyJsonReader(reader); + } + + @Override + public JsonReader createReader(InputStream in) { + System.out.println("public JsonReader createReader(InputStream)"); + addCalls("public JsonReader createReader(InputStream)"); + return new MyJsonReader(in); + } + + @Override + public JsonReaderFactory createReaderFactory(Map<String, ?> config) { + System.out.println( + "public JsonReaderFactory createReaderFactory(Map<String, ?>)"); + addCalls("public JsonReaderFactory createReaderFactory(Map<String, ?>)"); + return null; + } + + @Override + public JsonWriter createWriter(Writer writer) { + System.out.println("public JsonWriter createWriter(Writer)"); + addCalls("public JsonWriter createWriter(Writer)"); + return new MyJsonWriter(writer); + } + + @Override + public JsonWriter createWriter(OutputStream out) { + System.out.println("public JsonWriter createWriter(OutputStream)"); + addCalls("public JsonWriter createWriter(OutputStream)"); + return new MyJsonWriter(out); + } + + @Override + public JsonWriterFactory createWriterFactory(Map<String, ?> config) { + System.out.println( + "public JsonWriterFactory createWriterFactory(Map<String, ?>)"); + addCalls("public JsonWriterFactory createWriterFactory(Map<String, ?>)"); + return null; + } + + @Override + public JsonGenerator createGenerator(Writer writer) { + System.out.println("public JsonGenerator createGenerator(Writer)"); + addCalls("public JsonGenerator createGenerator(Writer)"); + return new MyJsonGenerator(writer); + } + + @Override + public JsonGenerator createGenerator(OutputStream out) { + System.out.println("public JsonGenerator createGenerator(OutputStream)"); + addCalls("public JsonGenerator createGenerator(OutputStream)"); + return new MyJsonGenerator(out); + } + + @Override + public JsonParser createParser(Reader reader) { + System.out.println("public JsonParser createParser(Reader)"); + addCalls("public JsonParser createParser(Reader)"); + return new MyJsonParser(reader); + } + + @Override + public JsonParser createParser(InputStream in) { + System.out.println("public JsonParser createParser(InputStream)"); + addCalls("public JsonParser createParser(InputStream)"); + if (in == null) + throw exception; + else + return new MyJsonParser(in); + } + + @Override + public JsonParserFactory createParserFactory(Map<String, ?> config) { + System.out.println( + "public JsonParserFactory createParserFactory(Map<String, ?>)"); + addCalls("public JsonParserFactory createParserFactory(Map<String, ?>)"); + return null; + } + + @Override + public JsonGeneratorFactory createGeneratorFactory(Map<String, ?> config) { + System.out.println( + "public JsonGeneratorFactory createGeneratorFactory(Map<String, ?>)"); + addCalls( + "public JsonGeneratorFactory createGeneratorFactory(Map<String, ?>)"); + return null; + } + + @Override + public JsonPatchBuilder createPatchBuilder() { + throw new UnsupportedOperationException("Not supported yet."); // To change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonPatchBuilder createPatchBuilder(JsonArray ja) { + throw new UnsupportedOperationException("Not supported yet."); // To change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + +}
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonReader.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonReader.java new file mode 100644 index 0000000..a74c203 --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonReader.java
@@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.provider; + +import jakarta.json.*; +import jakarta.json.stream.*; +import jakarta.json.spi.JsonProvider; +import java.io.*; +import java.nio.charset.Charset; +import java.util.*; + +/* + * MyJsonReader is a Json Test Reader used by the pluggability tests + * to test the Json SPI layer. This parser tracks that the proper callback + * methods are invoked within the parser when Json API methods are called. + */ + +public class MyJsonReader implements JsonReader { + private InputStream in = null; + + private Reader reader = null; + + private void dumpInstanceVars() { + System.out.println("reader=" + reader); + System.out.println("in=" + in); + } + + // call methods + private static StringBuilder calls = new StringBuilder(); + + public static String getCalls() { + return calls.toString(); + } + + public static void clearCalls() { + calls.delete(0, calls.length()); + } + + private static void addCalls(String s) { + calls.append(s); + } + + public MyJsonReader() { + } + + public MyJsonReader(InputStream in) { + this.in = in; + } + + public MyJsonReader(Reader reader) { + this.reader = reader; + } + + public void close() { + System.out.println("public void close()"); + addCalls("public void close()"); + } + + public JsonStructure read() { + System.out.println("public void read()"); + addCalls("public void read()"); + return null; + } + + public JsonArray readArray() { + System.out.println("public void readArray()"); + addCalls("public void readArray()"); + return null; + } + + public JsonObject readObject() { + System.out.println("public void readObject()"); + addCalls("public void readObject()"); + return null; + } +}
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonReaderFactory.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonReaderFactory.java new file mode 100644 index 0000000..d58b9a2 --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonReaderFactory.java
@@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.provider; + +import jakarta.json.*; +import java.io.*; +import java.nio.charset.Charset; +import java.util.*; + +/* + * MyJsonReaderFactory is a Json Test ReaderFactory used by the pluggability tests + * to test the Json SPI layer. This parser tracks that the proper callback + * methods are invoked within the parser when Json API methods are called. + */ +public class MyJsonReaderFactory implements JsonReaderFactory { + private InputStream in = null; + + private Charset charset = null; + + private Reader reader = null; + + private Map<String, ?> config = null; + + private void dumpInstanceVars() { + System.out.println("reader=" + reader); + System.out.println("in=" + in); + System.out.println("charset=" + charset); + System.out.println("config=" + config); + } + + // call methods + private static StringBuilder calls = new StringBuilder(); + + public static String getCalls() { + return calls.toString(); + } + + public static void clearCalls() { + calls.delete(0, calls.length()); + } + + private static void addCalls(String s) { + calls.append(s); + } + + public MyJsonReaderFactory(Map<String, ?> config) { + this.config = config; + } + + public Map<String, ?> getConfigInUse() { + System.out.println("public Map<String, ?> getConfigInUse()"); + addCalls("public Map<String, ?> getConfigInUse()"); + return config; + } + + public JsonReader createReader(InputStream in) { + System.out.println("public JsonReader createReader(InputStream)"); + addCalls("public JsonReader createReader(InputStream)"); + this.in = in; + return null; + } + + public JsonReader createReader(InputStream in, Charset charset) { + System.out.println("public JsonReader createReader(InputStream, Charset)"); + addCalls("public JsonReader createReader(InputStream, Charset)"); + this.in = in; + this.charset = charset; + return null; + } + + public JsonReader createReader(Reader reader) { + System.out.println("public JsonReader createReader(Reader)"); + addCalls("public JsonReader createReader(Reader)"); + this.reader = reader; + return null; + } +}
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonWriter.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonWriter.java new file mode 100644 index 0000000..a3321f0 --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonWriter.java
@@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.provider; + +import jakarta.json.*; +import jakarta.json.stream.*; +import jakarta.json.spi.JsonProvider; +import java.io.*; +import java.nio.charset.Charset; +import java.util.*; + +/* + * MyJsonWriter is a Json Test Writer used by the pluggability tests + * to test the Json SPI layer. This parser tracks that the proper callback + * methods are invoked within the parser when Json API methods are called. + */ +public class MyJsonWriter implements JsonWriter { + private OutputStream out = null; + + private Writer writer = null; + + private Charset charset = Charset.forName("UTF-8"); + + private void dumpInstanceVars() { + System.out.println("writer=" + writer); + System.out.println("out=" + out); + System.out.println("charset=" + charset); + } + + // call methods + private static StringBuilder calls = new StringBuilder(); + + public static String getCalls() { + return calls.toString(); + } + + public static void clearCalls() { + calls.delete(0, calls.length()); + } + + private static void addCalls(String s) { + calls.append(s); + } + + public MyJsonWriter() { + } + + public MyJsonWriter(OutputStream out) { + this.out = out; + } + + public MyJsonWriter(Writer writer) { + this.writer = writer; + } + + public void close() { + System.out.println("public void close()"); + addCalls("public void close()"); + } + + public void write(JsonStructure value) { + System.out.println("public void write(JsonStructure)"); + addCalls("public void write(JsonStructure)"); + } + + public void writeArray(JsonArray array) { + System.out.println("public void writeArray(JsonArray)"); + addCalls("public void writeArray(JsonArray)"); + } + + public void writeObject(JsonObject object) { + System.out.println("public void writeObject(JsonObject)"); + addCalls("public void writeObject(JsonObject)"); + } +}
diff --git a/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonWriterFactory.java b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonWriterFactory.java new file mode 100644 index 0000000..f15cfbd --- /dev/null +++ b/tck/tck-tests-plugability/src/main/java/jakarta/jsonp/tck/provider/MyJsonWriterFactory.java
@@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ + +package jakarta.jsonp.tck.provider; + + +import jakarta.json.*; +import java.io.*; +import java.nio.charset.Charset; +import java.util.*; + +/* + * MyJsonWriterFactory is a Json Test WriterFactory used by the pluggability tests + * to test the Json SPI layer. This parser tracks that the proper callback + * methods are invoked within the parser when Json API methods are called. + */ +public class MyJsonWriterFactory implements JsonWriterFactory { + private OutputStream out = null; + + private Writer writer = null; + + private Charset charset = null; + + private Map<String, ?> config = null; + + private void dumpInstanceVars() { + System.out.println("writer=" + writer); + System.out.println("out=" + out); + System.out.println("charset=" + charset); + System.out.println("config=" + config); + } + + // call methods + private static StringBuilder calls = new StringBuilder(); + + public static String getCalls() { + return calls.toString(); + } + + public static void clearCalls() { + calls.delete(0, calls.length()); + } + + private static void addCalls(String s) { + calls.append(s); + } + + public MyJsonWriterFactory(Map<String, ?> config) { + this.config = config; + } + + public Map<String, ?> getConfigInUse() { + System.out.println("public Map<String, ?> getConfigInUse()"); + addCalls("public Map<String, ?> getConfigInUse()"); + return config; + } + + public JsonWriter createWriter(OutputStream out) { + System.out.println("public JsonWriter createWriter(OutputStream)"); + addCalls("public JsonWriter createWriter(OutputStream)"); + this.out = out; + return null; + } + + public JsonWriter createWriter(OutputStream out, Charset charset) { + System.out.println("public JsonWriter createWriter(OutputStream, Charset)"); + addCalls("public JsonWriter createWriter(OutputStream, Charset)"); + this.out = out; + this.charset = charset; + return null; + } + + public JsonWriter createWriter(Writer writer) { + System.out.println("public JsonWriter createWriter(Writer)"); + addCalls("public JsonWriter createWriter(Writer)"); + this.writer = writer; + return null; + } +}
diff --git a/tck/tck-tests-plugability/src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider b/tck/tck-tests-plugability/src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider new file mode 100644 index 0000000..997ae9a --- /dev/null +++ b/tck/tck-tests-plugability/src/main/resources/META-INF/services/jakarta.json.spi.JsonProvider
@@ -0,0 +1 @@ +jakarta.jsonp.tck.provider.MyJsonProvider
diff --git a/tck/tck-tests/pom.xml b/tck/tck-tests/pom.xml new file mode 100644 index 0000000..af1c6d0 --- /dev/null +++ b/tck/tck-tests/pom.xml
@@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck</artifactId> + <version>2.0.0-SNAPSHOT</version> + </parent> + + <artifactId>jakarta.json-tck-tests</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>jakarta.json</groupId> + <artifactId>jakarta.json-tck-common</artifactId> + <version>2.0.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + </dependencies> + +</project>
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/collectortests/CollectorTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/collectortests/CollectorTests.java new file mode 100644 index 0000000..a15bc5e --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/collectortests/CollectorTests.java
@@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.collectortests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.lib.harness.Fault; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +// $Id$ +/** + * JavaScript Object Notation (JSON) Pointer compatibility tests.<br> + * Test {@link jakarta.json.stream.JsonCollectors} class implementation. + */ +@RunWith(Arquillian.class) +public class CollectorTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, CollectorTests.class.getPackage().getName()); + } + + /** + * Test JSON-P {@link jakarta.json.stream.JsonCollectors} class implementation. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonCollectorTest + * @assertion_ids: JSONP:JAVADOC:668; JSONP:JAVADOC:669; JSONP:JAVADOC:670; + * JSONP:JAVADOC:671; + * @test_Strategy: Test all collectors returned by API. + */ + @Test + public void jsonCollectorTest() throws Fault { + Collectors collectorTest = new Collectors(); + final TestResult result = collectorTest.test(); + result.eval(); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/collectortests/Collectors.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/collectortests/Collectors.java new file mode 100644 index 0000000..bffc445 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/collectortests/Collectors.java
@@ -0,0 +1,517 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.collectortests; + +import jakarta.jsonp.tck.api.common.TestResult; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Map; +import java.util.TreeSet; +import java.util.function.Function; +import java.util.stream.Collector; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonCollectors; +import jakarta.json.stream.JsonParser; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) Pointer compatibility tests.<br> + * Test {@link jakarta.json.stream.JsonCollectors} class implementation. This + * class was added to resolve + * {@see <a href="https://java.net/jira/browse/JSON_PROCESSING_SPEC-68">RFE: + * Support JSON queries using JDK's stream operations</a>}. + */ +public class Collectors { + + /** Tests input data with JsonArray instances. */ + private static final JsonArray[] ARRAY_VALUES = new JsonArray[] { + createSimpleStringArray5(), // JsonArray with String + createSimpleIntArray5(), // JsonArray with int + createSimpleBoolArray5(), // JsonArray with boolean + createSimpleObjectArray5() // JsonArray with JsonObject + }; + + /** Tests input data with JsonArray instances. */ + private static final JsonObject[] OBJ_VALUES = new JsonObject[] { + createSimpleObjectWithStr(), // JsonObject with String + createSimpleObjectWithInt(), // JsonObject with int + createSimpleObjectWithBool(), // JsonObject with boolean + createCompoundObject() // JsonObject with JsonObject + }; + + /** Test input data for {@code groupingBy} methods. */ + private static final JsonArray OBJ_ARRAY_GROUP = Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("name", "Peter").add("office", + "Green")) + .add(Json.createObjectBuilder().add("name", "John").add("office", "Red")) + .add(Json.createObjectBuilder().add("name", "Bob").add("office", "Blue")) + .add(Json.createObjectBuilder().add("name", "Sarah").add("office", "Red")) + .add(Json.createObjectBuilder().add("name", "Tom").add("office", "Blue")) + .add(Json.createObjectBuilder().add("name", "Jane").add("office", "Blue")) + .add(Json.createObjectBuilder().add("name", "Peggy").add("office", + "Green")) + .add(Json.createObjectBuilder().add("name", "Rick").add("office", "Red")) + .build(); + + /** + * Creates an instance of {@link jakarta.json.stream.JsonCollectors} class + * implementation tests. + */ + Collectors() { + super(); + } + + /** + * Test {@link jakarta.json.stream.JsonCollectors} class implementation. Suite + * entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonCollectors class implementation"); + System.out.println("JsonCollectors class implementation"); + testToJsonArrayCollector(result); + // testSimpleToJsonObjectCollector(result); + testToJsonObjectCollector(result); + testSimpleGroupingByCollector(result); + testSortingGroupingByCollector(result); + return result; + } + + /** + * Test collector returned by {@code toJsonArray()} method. This collector + * packs {@code Stream<JsonValue>} contend into a single JsonArray instance + * which contains stream values in the same order at they were read. It can be + * considered as {@link JsonParser#getArrayStream()} counterpart. + * + * @param result + * Tests result record. + */ + private void testToJsonArrayCollector(final TestResult result) { + System.out.println(" - Collector returned by toJsonArray()"); + for (final JsonArray in : ARRAY_VALUES) { + System.out.println(" - Input: " + valueToString(in)); + final Collector<JsonValue, JsonArrayBuilder, JsonArray> col = JsonCollectors + .toJsonArray(); + final JsonArray out = in.getValuesAs(JsonObject.class).stream() + .collect(col); + if (operationFailed(in, out)) { + result.fail("toJsonArray()", "Output Stream value " + valueToString(out) + + " shall be " + valueToString(in)); + } + } + } + + // TCK test for https://java.net/jira/browse/JSON_PROCESSING_SPEC-82 in case + // it will be checked in. + // /** + // * Test collector returned by {@code toJsonObject()} method. + // * This collector packs {@code Stream<JsonValue>} contend into a single + // JsonArray instance which contains + // * stream values in the same order at they were read. It can be considered + // as {@link JsonParser#getArrayStream()} + // * counterpart. + // * @param result Tests result record. + // */ + // private void testSimpleToJsonObjectCollector(final TestResult result) { + // System.out.println(" - Collector returned by toJsonObject()"); + // for (final JsonObject in : OBJ_VALUES) { + // System.out.println(" - Input: " + valueToString(in)); + // final Collector<Map.Entry<String,JsonValue>, JsonObjectBuilder, JsonObject> + // col = JsonCollectors.toJsonObject(); + // final JsonObject out = (in.entrySet()).stream().collect(col); + // if (operationFailed(in, out)) { + // result.fail("toJsonObject()", + // "Output Stream value " + valueToString(out) + " shall be " + + // valueToString(in)); + // } + // } + // } + + /** + * Test collector returned by + * {@code toJsonObject(Function<JsonValue,String>, Function<JsonValue,JsonValue>)} + * method. This collector does not pack content of + * {@code Stream<Map.Entry<String,JsonValue>>} stream of + * {@link JsonParser#getObjectStream()} output. So it's not counterpart of + * this method. It works with {@code Stream<JsonValue>}, which is + * {@link JsonParser#getArrayStream()} output and uses two {@link Function} + * implementations to build target object keys and values from + * {@code JsonValue} in the {@code Stream}. + * + * @param result + * Tests result record. + */ + private void testToJsonObjectCollector(final TestResult result) { + System.out.println(" - Collector returned by toJsonObject(Function,Function)"); + final JsonArray in = Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("key", STR_NAME).add("value", + STR_VALUE)) + .add(Json.createObjectBuilder().add("key", INT_NAME).add("value", + INT_VALUE)) + .add(Json.createObjectBuilder().add("key", BOOL_NAME).add("value", + BOOL_VALUE)) + .add(Json.createObjectBuilder().add("key", OBJ_NAME).add("value", + OBJ_VALUE)) + .build(); + final JsonObject check = Json.createObjectBuilder().add(STR_NAME, STR_VALUE) + .add(INT_NAME, INT_VALUE).add(BOOL_NAME, BOOL_VALUE) + .add(OBJ_NAME, OBJ_VALUE).build(); + System.out.println(" Input: " + valueToString(in)); + final Collector<JsonValue, JsonObjectBuilder, JsonObject> col = JsonCollectors + .toJsonObject( + // Build key from stream value. + (JsonValue v) -> { + if (v.getValueType() == JsonValue.ValueType.OBJECT) + return v.asJsonObject().getString("key"); + throw new IllegalStateException("Value must be JsonObject"); + }, + // Build value from stream value. + (JsonValue v) -> { + if (v.getValueType() == JsonValue.ValueType.OBJECT) + return v.asJsonObject().get("value"); + throw new IllegalStateException("Value must be JsonObject"); + }); + final JsonObject out = in.getValuesAs(JsonObject.class).stream() + .collect(col); + if (operationFailed(out, check)) { + result.fail("toJsonObject(Function,Function)", "Output Stream value " + + valueToString(out) + " shall be " + valueToString(check)); + } + } + + /** + * Test collector returned by {@code groupingBy(Function<JsonValue,String>)} + * method. This collector allows grouping of {@code Stream<JsonValue>} using + * provided {@code Function<JsonValue,String>)} function to define group + * identifiers based on {@code JsonValue} content. Test just groups JSON + * objects in the stream by {@code "office"} attribute. Default + * {@code toJsonArray()} collector is used so output is unsorted. + * + * @param result + * Tests result record. + */ + private void testSimpleGroupingByCollector(final TestResult result) { + System.out.println(" - Collector returned by groupingBy(Function)"); + final JsonObject check = Json.createObjectBuilder().add("Red", Json + .createArrayBuilder() + .add( + Json.createObjectBuilder().add("name", "John").add("office", "Red")) + .add(Json.createObjectBuilder().add("name", "Sarah").add("office", + "Red")) + .add( + Json.createObjectBuilder().add("name", "Rick").add("office", "Red")) + .build()) + .add("Blue", + Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("name", "Bob").add("office", + "Blue")) + .add(Json.createObjectBuilder().add("name", "Tom").add("office", + "Blue")) + .add(Json.createObjectBuilder().add("name", "Jane") + .add("office", "Blue")) + .build()) + .add("Green", + Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("name", "Peter") + .add("office", "Green")) + .add(Json.createObjectBuilder().add("name", "Peggy") + .add("office", "Green")) + .build()) + .build(); + System.out.println(" Input: " + valueToString(OBJ_ARRAY_GROUP)); + final Collector<JsonValue, Map<String, JsonArrayBuilder>, JsonObject> col = JsonCollectors + .groupingBy((JsonValue v) -> { + if (v.getValueType() == JsonValue.ValueType.OBJECT) + return v.asJsonObject().getString("office"); + throw new IllegalStateException("Value must be JsonObject"); + }); + final JsonObject out = OBJ_ARRAY_GROUP.getValuesAs(JsonObject.class) + .stream().collect(col); + if (operationFailed(out, check)) { + result.fail("groupingBy(Function)", "Output Stream value " + + valueToString(out) + " shall be " + valueToString(check)); + } + } + + /** + * Builder to create sorted JsonArray with ordering by {@code "name"} + * attribute of {@code JsonObject}. + */ + private class ValueBuilder implements JsonArrayBuilder { + + /** Sorted collection of values. */ + private final TreeSet<JsonValue> values; + + private ValueBuilder() { + values = new TreeSet<>((JsonValue v1, JsonValue v2) -> { + if (v1.getValueType() == JsonValue.ValueType.OBJECT + && v1.getValueType() == JsonValue.ValueType.OBJECT) { + return v1.asJsonObject().getString("name") + .compareTo(v2.asJsonObject().getString("name")); + } + throw new IllegalStateException("Values must be JsonObject"); + }); + } + + /** + * Builder accumulator method. + * + * @param value + * Value to be added to {@code JsonArray}. + * @return This builder instance. + */ + @Override + public JsonArrayBuilder add(JsonValue value) { + values.add(value); + return this; + } + + /** + * Builder combiner method. + * + * @param builder + * Builder containing values to be added to {@code JsonArray}. + * @return This builder instance. + */ + public ValueBuilder addAll(ValueBuilder builder) { + values.addAll(builder.values); + return this; + } + + /** + * Builder finisher method. + * + * @return {@code JsonArray} from current builder content. + */ + @Override + public JsonArray build() { + JsonArrayBuilder builder = Json.createArrayBuilder(); + for (JsonValue value : values) { + builder.add(value); + } + return builder.build(); + } + + @Override + public JsonArrayBuilder add(String value) { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonArrayBuilder add(BigDecimal value) { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonArrayBuilder add(BigInteger value) { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonArrayBuilder add(int value) { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonArrayBuilder add(long value) { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonArrayBuilder add(double value) { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonArrayBuilder add(boolean value) { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonArrayBuilder addNull() { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonArrayBuilder add(JsonObjectBuilder builder) { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + @Override + public JsonArrayBuilder add(JsonArrayBuilder builder) { + throw new UnsupportedOperationException("Not supported yet."); // To + // change + // body of + // generated + // methods, + // choose + // Tools | + // Templates. + } + + } + + /** + * Test collector returned by + * {@code groupingBy(Function<JsonValue,String>,Collector<JsonValue,JsonArrayBuilder,JsonArray>)} + * method. This collector allows grouping of {@code Stream<JsonValue>} using + * provided {@code Function<JsonValue,String>)} function to define group + * identifiers based on {@code JsonValue} content and + * {@code Collector<JsonValue,JsonArrayBuilder,JsonArray>)}. Test groups JSON + * objects in the stream by {@code "office"} attribute. External collector is + * building sorted {@code JsonArray} so arrays for each office group are + * sorted. + * + * @param result + * Tests result record. + */ + private void testSortingGroupingByCollector(final TestResult result) { + System.out.println(" - Collector returned by groupingBy(Function,Collector)"); + final JsonObject check = Json.createObjectBuilder().add("Red", Json + .createArrayBuilder() + .add( + Json.createObjectBuilder().add("name", "John").add("office", "Red")) + .add( + Json.createObjectBuilder().add("name", "Rick").add("office", "Red")) + .add(Json.createObjectBuilder().add("name", "Sarah").add("office", + "Red")) + .build()) + .add("Blue", + Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("name", "Bob").add("office", + "Blue")) + .add(Json.createObjectBuilder().add("name", "Jane") + .add("office", "Blue")) + .add(Json.createObjectBuilder().add("name", "Tom").add("office", + "Blue")) + .build()) + .add("Green", + Json.createArrayBuilder() + .add(Json.createObjectBuilder().add("name", "Peggy") + .add("office", "Green")) + .add(Json.createObjectBuilder().add("name", "Peter") + .add("office", "Green")) + .build()) + .build(); + Collector<JsonValue, JsonArrayBuilder, JsonArray> toArray = Collector.of( + ValueBuilder::new, JsonArrayBuilder::add, JsonArrayBuilder::addAll, + JsonArrayBuilder::build); + System.out.println(" Input: " + valueToString(OBJ_ARRAY_GROUP)); + final Collector<JsonValue, Map<String, JsonArrayBuilder>, JsonObject> col = JsonCollectors + .groupingBy((JsonValue v) -> { + if (v.getValueType() == JsonValue.ValueType.OBJECT) + return v.asJsonObject().getString("office"); + throw new IllegalStateException("Value must be JsonObject"); + }, toArray); + final JsonObject out = OBJ_ARRAY_GROUP.getValuesAs(JsonObject.class) + .stream().collect(col); + if (operationFailed(out, check)) { + result.fail("groupingBy(Function,Collector)", "Output Stream value " + + valueToString(out) + " shall be " + valueToString(check)); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + System.out.println(" Checking " + valueToString(out)); + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/ArrayBuilder.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/ArrayBuilder.java new file mode 100644 index 0000000..63abcfe --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/ArrayBuilder.java
@@ -0,0 +1,290 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +import java.math.BigDecimal; +import java.math.BigInteger; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonValue; + +// $Id$ +/** + * {@link JsonArrayBuilder} manipulation helper. + */ +public class ArrayBuilder { + + /** + * Add {@code value} to provided JSON array builder. + * + * @param builder + * Target JSON array builder. + * @param value + * Value to be added at the end of the array. + * @return JSON array builder containing new {@code value}. + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonArrayBuilder add(final JsonArrayBuilder builder, + final Object value) { + switch (JsonValueType.getType(value)) { + case String: + return builder.add((String) value); + case Integer: + return builder.add(((Integer) value).intValue()); + case Long: + return builder.add(((Long) value).intValue()); + case BigInteger: + return builder.add(((BigInteger) value)); + case Double: + return builder.add(((Double) value).doubleValue()); + case BigDecimal: + return builder.add(((BigDecimal) value)); + case Boolean: + return builder.add(((Boolean) value).booleanValue()); + case JsonValue: + return builder.add((JsonValue) value); + case Null: + return builder.addNull(); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + + /** + * Add {@code value} at specified index to provided JSON array builder. + * + * @param builder + * Target JSON array builder. + * @param index + * Array index of value to be added. + * @param value + * Value to be added at the end of the array. + * @return JSON array builder containing new {@code value}. + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonArrayBuilder add(final JsonArrayBuilder builder, + final int index, final Object value) { + switch (JsonValueType.getType(value)) { + case String: + return builder.add(index, (String) value); + case Integer: + return builder.add(index, ((Integer) value).intValue()); + case Long: + return builder.add(index, ((Long) value).longValue()); + case BigInteger: + return builder.add(index, ((BigInteger) value)); + case Double: + return builder.add(index, ((Double) value).doubleValue()); + case BigDecimal: + return builder.add(index, ((BigDecimal) value)); + case Boolean: + return builder.add(index, ((Boolean) value).booleanValue()); + case JsonValue: + return builder.add(index, (JsonValue) value); + case Null: + return builder.addNull(index); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + + /** + * Add {@code null} to provided JSON array builder. Every call shall throw an + * exception which depends on selected type. + * + * @param builder + * Target JSON array builder. + * @param type + * Type of method argument to use.. + * @return JSON array builder containing new {@code value}. + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonArrayBuilder add(final JsonArrayBuilder builder, + final JsonValueType type) { + switch (type) { + case String: + return builder.add((String) null); + case Integer: + throw new UnsupportedOperationException( + "Value null is not supported for int"); + case Long: + throw new UnsupportedOperationException( + "Value null is not supported for long"); + case BigInteger: + return builder.add((BigInteger) null); + case Double: + throw new UnsupportedOperationException( + "Value null is not supported for double"); + case BigDecimal: + return builder.add((BigDecimal) null); + case Boolean: + return builder.add((Boolean) null); + case JsonValue: + return builder.add((JsonValue) null); + case Null: + throw new UnsupportedOperationException( + "Value null is not supported for addNull()"); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + + /** + * Add {@code null} to provided JSON array builder. Every call shall throw an + * exception which depends on selected type. + * + * @param builder + * Target JSON array builder. + * @param index + * Array index of value to be added. + * @param type + * Type of method argument to use.. + * @return JSON array builder containing new {@code value}. + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonArrayBuilder add(final JsonArrayBuilder builder, + final int index, final JsonValueType type) { + switch (type) { + case String: + return builder.add(index, (String) null); + case Integer: + throw new UnsupportedOperationException( + "Value null is not supported for int"); + case Long: + throw new UnsupportedOperationException( + "Value null is not supported for long"); + case BigInteger: + return builder.add(index, (BigInteger) null); + case Double: + throw new UnsupportedOperationException( + "Value null is not supported for double"); + case BigDecimal: + return builder.add(index, (BigDecimal) null); + case Boolean: + return builder.add(index, (Boolean) null); + case JsonValue: + return builder.add(index, (JsonValue) null); + case Null: + throw new UnsupportedOperationException( + "Value null is not supported for addNull()"); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + + /** + * Set {@code value} at specified index to provided JSON array builder. + * + * @param builder + * Target JSON array builder. + * @param index + * Array index of value to be added. + * @param value + * Value to be set at the end of the array. + * @return JSON array builder containing new {@code value}. + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonArrayBuilder set(final JsonArrayBuilder builder, + final int index, final Object value) { + switch (JsonValueType.getType(value)) { + case String: + return builder.set(index, (String) value); + case Integer: + return builder.set(index, ((Integer) value).intValue()); + case Long: + return builder.set(index, ((Long) value).longValue()); + case BigInteger: + return builder.set(index, ((BigInteger) value)); + case Double: + return builder.set(index, ((Double) value).doubleValue()); + case BigDecimal: + return builder.set(index, ((BigDecimal) value)); + case Boolean: + return builder.set(index, ((Boolean) value).booleanValue()); + case JsonValue: + return builder.set(index, (JsonValue) value); + case Null: + return builder.setNull(index); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + + /** + * Set {@code null} to provided JSON array builder. Every call shall throw an + * exception which depends on selected type. + * + * @param builder + * Target JSON array builder. + * @param index + * Array index of value to be added. + * @param type + * Type of method argument to use.. + * @return JSON array builder containing new {@code value}. + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonArrayBuilder set(final JsonArrayBuilder builder, + final int index, final JsonValueType type) { + switch (type) { + case String: + return builder.set(index, (String) null); + case Integer: + throw new UnsupportedOperationException( + "Value null is not supported for int"); + case Long: + throw new UnsupportedOperationException( + "Value null is not supported for long"); + case BigInteger: + return builder.set(index, (BigInteger) null); + case Double: + throw new UnsupportedOperationException( + "Value null is not supported for double"); + case BigDecimal: + return builder.set(index, (BigDecimal) null); + case Boolean: + return builder.set(index, (Boolean) null); + case JsonValue: + return builder.set(index, (JsonValue) null); + case Null: + throw new UnsupportedOperationException( + "Value null is not supported for addNull()"); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + + /** + * Remove {@code value} at specified index from provided JSON array builder. + * + * @param builder + * Target JSON array builder. + * @param index + * Array index of value to be added. + * @return JSON array builder containing new {@code value}. + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonArrayBuilder remove(final JsonArrayBuilder builder, + final int index) { + return builder.remove(index); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/JsonAssert.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/JsonAssert.java new file mode 100644 index 0000000..6afd391 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/JsonAssert.java
@@ -0,0 +1,206 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +import java.io.StringReader; +import java.math.BigDecimal; +import java.math.BigInteger; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonNumber; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.common.JSONP_Util.toStringJsonArray; +import static jakarta.jsonp.tck.common.JSONP_Util.toStringJsonObject; + +// $Id$ +/** + * JSON values assertions. + */ +public class JsonAssert { + + private static boolean assertEquals(final JsonObject expected, + final JsonObject actual, final String message) { + if (actual.equals(expected)) { + return true; + } else { + System.out.println(" " + message); + System.out.println(" Expected: " + toStringJsonObject(expected)); + System.out.println(" Actual: " + toStringJsonObject(actual)); + return false; + } + } + + private static boolean assertEquals(final JsonArray expected, + final JsonArray actual, final String message) { + if (actual.equals(expected)) { + return true; + } else { + System.out.println(" " + message); + System.out.println(" Expected: " + toStringJsonArray(expected)); + System.out.println(" Actual: " + toStringJsonArray(actual)); + return false; + } + } + + private static boolean assertEquals(final JsonString expected, + final JsonString actual, final String message) { + if (actual.equals(expected)) { + return true; + } else { + System.out.println(" " + message); + System.out.println(" Expected: " + expected.getString()); + System.out.println(" Actual: " + actual.getString()); + return false; + } + } + + private static boolean assertEquals(final JsonNumber expected, + final JsonNumber actual, final String message) { + if (actual.equals(expected)) { + return true; + } else { + System.out.println(" " + message); + System.out.println(" Expected: " + expected.toString()); + System.out.println(" Actual: " + actual.toString()); + return false; + } + } + + public static boolean assertEquals(final JsonValue expected, + final JsonValue actual, final String message) { + switch (expected.getValueType()) { + case OBJECT: + return assertEquals((JsonObject) expected, (JsonObject) actual, message); + case ARRAY: + return assertEquals((JsonArray) expected, (JsonArray) actual, message); + case STRING: + return assertEquals((JsonString) expected, (JsonString) actual, message); + case NUMBER: + return assertEquals((JsonNumber) expected, (JsonNumber) actual, message); + case TRUE: + case FALSE: + if (expected == actual) { + return true; + } else { + System.out.println(" " + message); + System.out.println(" Expected: " + expected.toString()); + System.out.println(" Actual: " + actual.toString()); + return false; + } + default: + if (actual.equals(expected)) { + return true; + } else { + System.out.println(" " + message); + System.out.println(" Expected: " + expected.toString()); + System.out.println(" Actual: " + actual.toString()); + return false; + } + } + } + + public static boolean assertEquals(final JsonValue expected, + final JsonValue actual) { + return assertEquals(expected, actual, "JSON mismatch"); + } + + /** + * Operation result expected. + * + * @param expected + * Expected modified JSON value. + * @param actual + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + public static boolean assertEquals(final Object expected, + final String actual) { + if (actual == null) { + return true; + } + try { + switch (JsonValueType.getType(expected)) { + case String: + String exp = '\"' + (String) expected + '\"'; + return exp.equals(actual); + case Integer: + return Integer.parseInt(actual) == (Integer) expected; + case Long: + return Long.parseLong(actual) == (Long) expected; + case BigInteger: + return (new BigInteger(actual)).equals(expected); + case Double: + return Double.parseDouble(actual) == (Double) expected; + case BigDecimal: + return (new BigDecimal(actual)).equals(expected); + case Boolean: + return Boolean.parseBoolean(actual) == (Boolean) expected; + case JsonValue: + try (final JsonReader reader = Json + .createReader(new StringReader(actual))) { + final JsonValue actVal = reader.readValue(); + return assertEquals((JsonValue) expected, actVal); + } + case Null: + try (final JsonReader reader = Json + .createReader(new StringReader(actual))) { + final JsonValue actVal = reader.readValue(); + return assertEquals(JsonValue.NULL, actVal); + } + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } catch (NumberFormatException ex) { + return true; + } + } + + /** + * Convert provided JSON value to human readable String. + * + * @param value + * Value to be converted. + * @return JSON value as human readable String. + */ + public static String valueToString(final JsonValue value) { + switch (value.getValueType()) { + case OBJECT: + return toStringJsonObject((JsonObject) value); + case ARRAY: + return toStringJsonArray((JsonArray) value); + case STRING: + return ((JsonString) value).getString(); + case NUMBER: + return ((JsonNumber) value).toString(); + case TRUE: + return Boolean.toString(true); + case FALSE: + return Boolean.toString(false); + case NULL: + return "null"; + default: + throw new IllegalArgumentException("Unknown value type"); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/JsonIO.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/JsonIO.java new file mode 100644 index 0000000..1261a5e --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/JsonIO.java
@@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +import java.io.StringReader; +import jakarta.json.Json; +import jakarta.json.JsonValue; + +// $Id$ +/** + * Read and write JSON values. + */ +public class JsonIO { + /** + * Reads JSON value from {@code String}. + * + * @param json + * JSON value to be read. + * @return JSON value from provided {@code String}. + */ + public static JsonValue read(final String json) { + return Json.createReader(new StringReader(json)).readValue(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/JsonValueType.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/JsonValueType.java new file mode 100644 index 0000000..f8da982 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/JsonValueType.java
@@ -0,0 +1,137 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import jakarta.json.JsonValue; + +// $Id$ +/** + * Identifiers of types used as JSON value. + */ +public enum JsonValueType { + /** JsonValue is String. */ + String, + /** JsonValue is Integer. */ + Integer, + /** JsonValue is Long. */ + Long, + /** JsonValue is BigInteger. */ + BigInteger, + /** JsonValue is Double. */ + Double, + /** JsonValue is BigDecimal. */ + BigDecimal, + /** JsonValue is Boolean. */ + Boolean, + /** JsonValue is common JSON value. */ + JsonValue, + /** JsonValue is null. */ + Null; + + /** Size of this enumeration. */ + private static final int SIZE = JsonValueType.values().length; + + /** Name to value {@code Map}. */ + private static final Map<String, JsonValueType> VALUES = new HashMap<>(SIZE); + // Name to value Map initialization. + static { + for (int i = 0; i < SIZE; i++) + VALUES.put(JsonValueType.values()[i].name(), JsonValueType.values()[i]); + } + + /** + * Returns JSON value identifier for provided class. + * + * @param c + * JSON value class. + * @return JSON value identifier for provided class. + */ + public static JsonValueType getType(final Class c) { + JsonValueType type = VALUES.get(c.getSimpleName()); + if (type != null) { + return type; + } + // Interface hierarchy is a tree so stack machine is required to go trough + // it. + final LinkedList<Class> stack = new LinkedList(); + for (final Class i : c.getInterfaces()) { + stack.push(i); + } + while (!stack.isEmpty()) { + final Class i = stack.pop(); + type = VALUES.get(i.getSimpleName()); + if (type != null) { + return type; + } + for (final Class j : i.getInterfaces()) { + stack.push(j); + } + } + throw new IllegalArgumentException( + "Unsupported JSON value type: " + c.getSimpleName()); + } + + /** + * Returns JSON value identifier for provided value. + * + * @param value + * JSON value. + * @return JSON value identifier for provided class. + */ + public static JsonValueType getType(final Object value) { + return value != null ? getType(value.getClass()) : Null; + } + + /** + * Convert provided value to {@code String} which is part of JSON document. + * + * @param value + * Value be be converted to {@code String}. + * @return Value converted to {@code String}. + */ + public static String toStringValue(final Object value) { + switch (getType(value)) { + case String: + return '"' + ((String) value) + '"'; + case Integer: + return ((Integer) value).toString(); + case Long: + return ((Long) value).toString(); + case BigInteger: + return ((BigInteger) value).toString(); + case Double: + return ((Double) value).toString(); + case BigDecimal: + return ((BigDecimal) value).toString(); + case Boolean: + return ((Boolean) value).toString(); + case JsonValue: + return JsonAssert.valueToString((JsonValue) value); + case Null: + return SimpleValues.NULL; + default: + throw new IllegalArgumentException( + "Unsupported JSON value type: " + value.getClass().getSimpleName()); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/MergeRFCObject.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/MergeRFCObject.java new file mode 100644 index 0000000..54b6279 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/MergeRFCObject.java
@@ -0,0 +1,153 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; + +/* + * $Id$ + */ +/** + * {@see <a href="https://tools.ietf.org/html/rfc7396">RFC 7396</a>}: JavaScript + * Object Notation (JSON) Merge Patch compatibility sample object.<br> + * Object structure is defined in + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-3">RFC 7396: 3. + * Example</a>}. + */ +public class MergeRFCObject { + + // Following values define JSON object keys from RFC 7396: 3. Example + /** RFC 7396 sample JSON object key for {@code /title}. */ + public static final String KEY_TITLE = "title"; + + /** RFC 7396 sample JSON object key for {@code /author/givenName}. */ + public static final String KEY_GIVEN_NAME = "givenName"; + + /** RFC 7396 sample JSON object key for {@code /author/familyName}. */ + public static final String KEY_FAMILY_NAME = "familyName"; + + /** RFC 7396 sample JSON object key for {@code /author}. */ + public static final String KEY_AUTHOR = "author"; + + /** RFC 7396 sample JSON object key for {@code /tags}. */ + public static final String KEY_TAGS = "tags"; + + /** RFC 7396 sample JSON object key for {@code /content}. */ + public static final String KEY_CONTENT = "content"; + + /** RFC 7396 sample JSON object key for {@code /phoneNumber}. */ + public static final String KEY_PHONE_NUMBER = "phoneNumber"; + + // Following values define JSON object source values from RFC 7396: 3. Example + /** RFC 7396 sample JSON object source value for {@code /title}. */ + public static final String VAL_SRC_TITLE = "Goodbye!"; + + /** RFC 7396 sample JSON object source value for {@code /author/givenName}. */ + public static final String VAL_SRC_GIVEN_NAME = "John"; + + /** + * RFC 7396 sample JSON object source value for {@code /author/familyName}. + */ + public static final String VAL_SRC_FAMILY_NAME = "Doe"; + + /** RFC 7396 sample JSON object source value for {@code /author}. */ + public static final JsonObject VAL_SRC_AUTHOR = SimpleValues + .createSimpleObject(new String[] { KEY_GIVEN_NAME, KEY_FAMILY_NAME }, + new Object[] { VAL_SRC_GIVEN_NAME, VAL_SRC_FAMILY_NAME }); + + /** RFC 7396 sample JSON object source value for {@code /tags/0}. */ + public static final String VAL_SRC_TAGS_0 = "example"; + + /** RFC 7396 sample JSON object source value for {@code /tags/1}. */ + public static final String VAL_SRC_TAGS_1 = "sample"; + + /** RFC 7396 sample JSON object source value for {@code /tags}. */ + public static final JsonArray VAL_SRC_TAGS = SimpleValues + .createStringArray(new String[] { VAL_SRC_TAGS_0, VAL_SRC_TAGS_1 }); + + /** RFC 7396 sample JSON object source value for {@code /content}. */ + public static final String VAL_SRC_CONTENT = "This will be unchanged"; + + // Following values define JSON object target values from RFC 7396: 3. Example + /** RFC 7396 sample JSON object target value for {@code /title}. */ + public static final String VAL_TRG_TITLE = "Hello!"; + + /** RFC 7396 sample JSON object target value for {@code /author}. */ + public static final JsonObject VAL_TRG_AUTHOR = SimpleValues + .createSimpleObject(new String[] { KEY_GIVEN_NAME }, + new Object[] { VAL_SRC_GIVEN_NAME }); + + /** RFC 7396 sample JSON object target value for {@code /phoneNumber}. */ + public static final String VAL_TRG_PHONE_NUMBER = "+01-123-456-7890"; + + /** RFC 7396 sample JSON object target value for {@code /tags/0}. */ + public static final String VAL_TRG_TAGS_0 = "example"; + + /** RFC 7396 sample JSON object target value for {@code /tags}. */ + public static final JsonArray VAL_TRG_TAGS = SimpleValues + .createStringArray(new String[] { VAL_TRG_TAGS_0 }); + + // Following values define JSON object patch values from RFC 7396: 3. Example + /** RFC 7396 sample JSON object patch value for {@code /author/familyName}. */ + public static final JsonValue VAL_PATCH_FAMILY_NAME = JsonValue.NULL; + + /** RFC 7396 sample JSON object patch value for {@code /author}. */ + public static final JsonObject VAL_PATCH_AUTHOR = SimpleValues + .createSimpleObject(new String[] { KEY_FAMILY_NAME }, + new Object[] { VAL_PATCH_FAMILY_NAME }); + + /** + * Create {@see <a href="https://tools.ietf.org/html/rfc7396#section-3">RFC + * 7396 example</a>} source JSON object. + * + * @return Source object from example. + */ + public static JsonObject createRFCSourceObject() { + return Json.createObjectBuilder().add(KEY_TITLE, VAL_SRC_TITLE) + .add(KEY_AUTHOR, VAL_SRC_AUTHOR).add(KEY_TAGS, VAL_SRC_TAGS) + .add(KEY_CONTENT, VAL_SRC_CONTENT).build(); + } + + /** + * Create {@see <a href="https://tools.ietf.org/html/rfc7396#section-3">RFC + * 7396 example</a>} target JSON object. + * + * @return Target object from example. + */ + public static JsonObject createRFCTargetObject() { + return Json.createObjectBuilder().add(KEY_TITLE, VAL_TRG_TITLE) + .add(KEY_AUTHOR, VAL_TRG_AUTHOR).add(KEY_TAGS, VAL_TRG_TAGS) + .add(KEY_CONTENT, VAL_SRC_CONTENT) + .add(KEY_PHONE_NUMBER, VAL_TRG_PHONE_NUMBER).build(); + } + + /** + * Create {@see <a href="https://tools.ietf.org/html/rfc7396#section-3">RFC + * 7396 example</a>} patch JSON object. + * + * @return Patch object from example. + */ + public static JsonObject createRFCPatchObject() { + return Json.createObjectBuilder().add(KEY_TITLE, VAL_TRG_TITLE) + .add(KEY_PHONE_NUMBER, VAL_TRG_PHONE_NUMBER) + .add(KEY_AUTHOR, VAL_PATCH_AUTHOR).add(KEY_TAGS, VAL_TRG_TAGS).build(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/ObjectBuilder.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/ObjectBuilder.java new file mode 100644 index 0000000..e31f468 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/ObjectBuilder.java
@@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +import java.math.BigDecimal; +import java.math.BigInteger; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; + +// $Id$ +/** + * {@link JsonObjectBuilder} manipulation helper. + */ +public class ObjectBuilder { + + /** + * Add {@code value} with {@code name} to provided JSON object builder. + * + * @param builder + * Target JSON object builder. + * @param name + * Name of value to be added. + * @param value + * Value to be added. + * @return JSON object builder containing new {@code value}. + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonObjectBuilder add(final JsonObjectBuilder builder, + final String name, final Object value) { + switch (JsonValueType.getType(value)) { + case String: + return builder.add(name, (String) value); + case Integer: + return builder.add(name, ((Integer) value).intValue()); + case Long: + return builder.add(name, ((Long) value).intValue()); + case BigInteger: + return builder.add(name, ((BigInteger) value)); + case Double: + return builder.add(name, ((Double) value).doubleValue()); + case BigDecimal: + return builder.add(name, ((BigDecimal) value)); + case Boolean: + return builder.add(name, ((Boolean) value).booleanValue()); + case JsonValue: + return builder.add(name, (JsonValue) value); + case Null: + return builder.addNull(name); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/PointerRFCObject.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/PointerRFCObject.java new file mode 100644 index 0000000..b648d3c --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/PointerRFCObject.java
@@ -0,0 +1,183 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; + +/* + * $Id$ + */ +/** + * {@see <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>}: JavaScript + * Object Notation (JSON) Pointer compatibility sample object.<br> + * Object structure is defined in + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-5">RFC 6901: 5. + * JSON String Representation</a>}. + */ +public class PointerRFCObject { + + // Following values define JSON object from + // RFC 6901: 5. JSON String Representation + // https://tools.ietf.org/html/rfc6901#section-5 + /** RFC 6901 sample JSON object key for the whole document. */ + public static final String RFC_KEY_WHOLE = ""; + + /** RFC 6901 sample JSON object key for 1st value. */ + public static final String RFC_KEY1 = "foo"; + + /** RFC 6901 sample JSON object pointer for 1st value. */ + public static final String RFC_PTR1 = "/foo"; + + /** RFC 6901 sample JSON object pointer for 1st item of 1st value. */ + public static final String RFC_PTR1_ITEM1 = "/foo/0"; + + /** RFC 6901 sample JSON object pointer for 2nd item of 1st value. */ + public static final String RFC_PTR1_ITEM2 = "/foo/1"; + + /** RFC 6901 sample JSON object 1st value: array 1st item. */ + public static final String RFC_VAL1_ITEM1 = "bar"; + + /** RFC 6901 sample JSON object 1st value: array 2nd item. */ + public static final String RFC_VAL1_ITEM2 = "baz"; + + /** RFC 6901 sample JSON object 1st value. */ + public static final JsonArray RFC_VAL1 = SimpleValues + .createStringArray(RFC_VAL1_ITEM1, RFC_VAL1_ITEM2); + + /** RFC 6901 sample JSON object key for 2nd value. */ + public static final String RFC_KEY2 = ""; + + /** RFC 6901 sample JSON object pointer for 2nd value. */ + public static final String RFC_PTR2 = "/"; + + /** RFC 6901 sample JSON object 2nd value. */ + public static final int RFC_VAL2 = 0; + + /** RFC 6901 sample JSON object key for 3rd value. */ + public static final String RFC_KEY3 = "a/b"; + + /** RFC 6901 sample JSON object pointer for 3rd value. */ + public static final String RFC_PTR3_ENC = "/a~1b"; + + /** RFC 6901 sample JSON object pointer for 3rd value. */ + public static final String RFC_PTR3 = "/a/b"; + + /** RFC 6901 sample JSON object 3rd value. */ + public static final int RFC_VAL3 = 1; + + /** RFC 6901 sample JSON object key for 4th value. */ + public static final String RFC_KEY4 = "c%d"; + + /** RFC 6901 sample JSON object pointer for 4th value. */ + public static final String RFC_PTR4 = "/c%d"; + + /** RFC 6901 sample JSON object 4th value. */ + public static final int RFC_VAL4 = 2; + + /** RFC 6901 sample JSON object key for 5th value. */ + public static final String RFC_KEY5 = "e^f"; + + /** RFC 6901 sample JSON object pointer for 5th value. */ + public static final String RFC_PTR5 = "/e^f"; + + /** RFC 6901 sample JSON object 5th value. */ + public static final int RFC_VAL5 = 3; + + /** RFC 6901 sample JSON object key for 6th value. */ + public static final String RFC_KEY6 = "g|h"; + + /** RFC 6901 sample JSON object pointer for 6th value. */ + public static final String RFC_PTR6 = "/g|h"; + + /** RFC 6901 sample JSON object 6th value. */ + public static final int RFC_VAL6 = 4; + + /** RFC 6901 sample JSON object key for 7th value. */ + public static final String RFC_KEY7 = "i\\j"; + + /** RFC 6901 sample JSON object pointer for 7th value. */ + public static final String RFC_PTR7 = "/i\\j"; + + /** RFC 6901 sample JSON object 7th value. */ + public static final int RFC_VAL7 = 5; + + /** RFC 6901 sample JSON object key for 8th value. */ + public static final String RFC_KEY8 = "k\"l"; + + /** RFC 6901 sample JSON object pointer for 8th value. */ + public static final String RFC_PTR8 = "/k\"l"; + + /** RFC 6901 sample JSON object 8th value. */ + public static final int RFC_VAL8 = 6; + + /** RFC 6901 sample JSON object key for 9th value. */ + public static final String RFC_KEY9 = " "; + + /** RFC 6901 sample JSON object pointer for 9th value. */ + public static final String RFC_PTR9 = "/ "; + + /** RFC 6901 sample JSON object 9th value. */ + public static final int RFC_VAL9 = 7; + + /** RFC 6901 sample JSON object key for 10th value. */ + public static final String RFC_KEY10 = "m~n"; + + /** RFC 6901 sample JSON object encoded pointer for 10th value. */ + public static final String RFC_KEY10_ENC = "/m~0n"; + + /** RFC 6901 sample JSON object pointer for 10th value. */ + public static final String RFC_PTR10 = "/m~n"; + + /** RFC 6901 sample JSON object 10th value. */ + public static final int RFC_VAL10 = 8; + + /** RFC 6901 sample JSON object key for 11th value. */ + public static final String RFC_KEY11 = "o~1p"; + + /** RFC 6901 sample JSON object encoded pointer for 11th value. */ + public static final String RFC_PTR11_ENC = "/o~01p"; + + /** RFC 6901 sample JSON object pointer for 11th value. */ + public static final String RFC_PTR11 = "/o~1p"; + + /** RFC 6901 sample JSON object 11th value. */ + public static final int RFC_VAL11 = 9; + + /** + * Creates RFC 6901 sample JSON object. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-5">RFC 6901: 5. + * JSON String Representation</a>} + * + * @return RFC 6901 sample JSON object. + */ + public static JsonObject createRFC6901Object() { + return Json.createObjectBuilder().add(RFC_KEY1, RFC_VAL1) + .add(RFC_KEY2, RFC_VAL2).add(RFC_KEY3, RFC_VAL3).add(RFC_KEY4, RFC_VAL4) + .add(RFC_KEY5, RFC_VAL5).add(RFC_KEY6, RFC_VAL6).add(RFC_KEY7, RFC_VAL7) + .add(RFC_KEY8, RFC_VAL8).add(RFC_KEY9, RFC_VAL9) + .add(RFC_KEY10, RFC_VAL10).add(RFC_KEY11, RFC_VAL11).build(); + } + + /** + * Create an instance of RFC 6901 object class is not allowed. + */ + private PointerRFCObject() { + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/SimpleValues.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/SimpleValues.java new file mode 100644 index 0000000..7ebe2b5 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/SimpleValues.java
@@ -0,0 +1,1155 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.BigInteger; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonPatch; +import jakarta.json.JsonValue; +import jakarta.json.JsonWriter; + +// $Id$ +/** + * RFC 6902: JavaScript Object Notation (JSON) Patch compatibility tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>}. + * <p> + * Build various simple values for testing. + */ +public class SimpleValues { + + /** Name of JSON {@code String} value used in tests. */ + public static final String STR_NAME = "address"; + + /** Path of JSON {@code String} value used in tests. */ + public static final String STR_PATH = "/" + STR_NAME; + + /** JSON {@code String} value used in tests. */ + public static final String STR_VALUE = "In a galaxy far far away"; + + /** JSON {@code String} second value used in tests. */ + public static final String STR_VALUE2 = "In a land of myth"; + + /** Name of JSON {@code int} value used in tests. */ + public static final String INT_NAME = "age"; + + /** Path of JSON {@code int} value used in tests. */ + public static final String INT_PATH = "/" + INT_NAME; + + /** JSON {@code int} value used in tests. */ + public static final int INT_VALUE = 42; + + /** JSON {@code int} second value used in tests. */ + public static final int INT_VALUE2 = 32; + + /** Name of JSON {@code boolean} value used in tests. */ + public static final String BOOL_NAME = "married"; + + /** Path of JSON {@code boolean} value used in tests. */ + public static final String BOOL_PATH = "/" + BOOL_NAME; + + /** JSON {@code boolean} value used in tests. */ + public static final boolean BOOL_VALUE = true; + + /** JSON {@code boolean} second value used in tests. */ + public static final boolean BOOL_VALUE2 = false; + + /** Name of JSON {@code JsonObject} value used in tests. */ + public static final String OBJ_NAME = "wife"; + + /** Path of JSON {@code JsonObject} value used in tests. */ + public static final String OBJ_PATH = "/" + OBJ_NAME; + + /** JSON {@code JsonObject} value used in tests. */ + public static final JsonObject OBJ_VALUE = createSimpleObject( + new String[] { "name", "age" }, new Object[] { "Sarah Connor", 32 }); + + /** JSON {@code JsonObject} second value used in tests. */ + public static final JsonObject OBJ_VALUE2 = createSimpleObject( + new String[] { "name", "age" }, new Object[] { "Kyle Reese", 35 }); + + /** Name of JSON default value stored in simple object. */ + public static final String DEF_NAME = "name"; + + /** Name of JSON default value stored in simple object. */ + public static final String DEF_PATH = "/" + DEF_NAME; + + /** JSON default value stored in simple object. */ + public static final String DEF_VALUE = "John Smith"; + + /** Name of JSON object stored in compound object. */ + public static final String DEF_OBJ_NAME = "child"; + + /** Path of JSON object stored in compound object. */ + public static final String DEF_OBJ_PATH = "/child"; + + /** JSON default object stored in simple object. */ + public static final JsonObject DEF_OBJ_VALUE = createSimpleObject( + new String[] { "name", "age" }, new Object[] { "John Connor", 6 }); + + /** JSON default object stored in simple object with name changed. */ + public static final JsonObject DEF_OBJ_VALUE2 = createSimpleObject( + new String[] { "name", "age" }, new Object[] { "John Smith", 6 }); + + /** Value of JSON {@code String} array at index 0. */ + public static final String STR_VALUE_1 = "First value"; + + /** Value of JSON {@code String} array at index 1. */ + public static final String STR_VALUE_2 = "Second value"; + + /** Value of JSON {@code String} array at index 2. */ + public static final String STR_VALUE_3 = "Third value"; + + /** Value of JSON {@code String} array at index 3. */ + public static final String STR_VALUE_4 = "Fourth value"; + + /** Value of JSON {@code String} array at index 4. */ + public static final String STR_VALUE_5 = "Fifth value"; + + /** Value of JSON {@code String} array at index 5. */ + public static final String STR_VALUE_6 = "Sixth value"; + + /** Value of JSON {@code String} array at index 6. */ + public static final String STR_VALUE_7 = "Seventh value"; + + /** Value of JSON {@code int} array at index 0. */ + public static final int INT_VALUE_1 = 1; + + /** Value of JSON {@code int} array at index 1. */ + public static final int INT_VALUE_2 = 2; + + /** Value of JSON {@code int} array at index 2. */ + public static final int INT_VALUE_3 = 3; + + /** Value of JSON {@code int} array at index 3. */ + public static final int INT_VALUE_4 = 4; + + /** Value of JSON {@code int} array at index 4. */ + public static final int INT_VALUE_5 = 5; + + /** Value of JSON {@code JsonObject} array at index 0. */ + public static final JsonObject OBJ_VALUE_1 = createSimpleObject( + new String[] { "first" }, new String[] { STR_VALUE_1 }); + + /** Value of JSON {@code JsonObject} array at index 1. */ + public static final JsonObject OBJ_VALUE_2 = createSimpleObject( + new String[] { "second" }, new String[] { STR_VALUE_2 }); + + /** Value of JSON {@code JsonObject} array at index 2. */ + public static final JsonObject OBJ_VALUE_3 = createSimpleObject( + new String[] { "third" }, new String[] { STR_VALUE_3 }); + + /** Value of JSON {@code JsonObject} array at index 3. */ + public static final JsonObject OBJ_VALUE_4 = createSimpleObject( + new String[] { "fourth" }, new String[] { STR_VALUE_4 }); + + /** Value of JSON {@code JsonObject} array at index 4. */ + public static final JsonObject OBJ_VALUE_5 = createSimpleObject( + new String[] { "fifth" }, new String[] { STR_VALUE_5 }); + + /** JSON {@code boolean} value: {@code true}. */ + public static final boolean BOOL_TRUE = true; + + /** JSON {@code boolean} value: {@code false}. */ + public static final boolean BOOL_FALSE = false; + + /** JSON {@code long} value used in tests. */ + public static final long LNG_VALUE = Long.MAX_VALUE - 42; + + /** JSON {@code BigInteger} value used in tests. */ + public static final BigInteger BIN_VALUE = new BigInteger( + "123456789012345678901234567890"); + + /** JSON {@code double} value used in tests. */ + public static final double DBL_VALUE = 0x1.f5c926b3a0942P+1014; + + /** JSON {@code BigDecimal} value used in tests. */ + public static final BigDecimal BDC_VALUE = new BigDecimal( + new BigInteger("1234567890123456789012345678901234567890"), 10); + + /** Message content: null String. */ + public static final String NULL = "null"; + + /** + * Creates empty JSON object. + * + * @return Empty JSON object. + */ + public static JsonObject createEmptyObject() { + return Json.createObjectBuilder().build(); + } + + /** + * Creates empty JSON object after ADD STR_NAME STR_VALUE operation. + * + * @return Empty JSON object after ADD STR_NAME STR_VALUE operation. + */ + public static JsonObject createSimpleObjectStr() { + return Json.createObjectBuilder().add(STR_NAME, STR_VALUE).build(); + } + + /** + * Creates empty JSON object after ADD INT_NAME INT_VALUE operation. + * + * @return Empty JSON object after ADD INT_NAME INT_VALUE operation. + */ + public static JsonObject createSimpleObjectInt() { + return Json.createObjectBuilder().add(INT_NAME, INT_VALUE).build(); + } + + /** + * Creates empty JSON object after ADD BOOL_NAME BOOL_VALUE operation. + * + * @return Empty JSON object after ADD BOOL_NAME BOOL_VALUE operation. + */ + public static JsonObject createSimpleObjectBool() { + return Json.createObjectBuilder().add(BOOL_NAME, BOOL_VALUE).build(); + } + + /** + * Creates empty JSON object after ADD OBJ_NAME OBJ_VALUE operation. + * + * @return Empty JSON object after ADD OBJ_NAME OBJ_VALUE operation. + */ + public static JsonObject createSimpleObjectObject() { + return Json.createObjectBuilder().add(OBJ_NAME, OBJ_VALUE).build(); + } + + /** + * Creates JSON patch to remove STR_NAME attribute from object. + * + * @return JSON patch + */ + public static JsonObject createPatchRemoveStr() { + return Json.createObjectBuilder().add(STR_NAME, JsonValue.NULL).build(); + } + + /** + * Creates JSON patch to remove INT_NAME attribute from object. + * + * @return JSON patch + */ + public static JsonObject createPatchRemoveInt() { + return Json.createObjectBuilder().add(INT_NAME, JsonValue.NULL).build(); + } + + /** + * Creates JSON patch to remove BOOL_NAME attribute from object. + * + * @return JSON patch + */ + public static JsonObject createPatchRemoveBool() { + return Json.createObjectBuilder().add(BOOL_NAME, JsonValue.NULL).build(); + } + + /** + * Creates JSON patch to remove OBJ_NAME attribute from object. + * + * @return JSON patch + */ + public static JsonObject createPatchRemoveObject() { + return Json.createObjectBuilder().add(OBJ_NAME, JsonValue.NULL).build(); + } + + /** + * Creates empty JSON array. + * + * @return Empty JSON array. + */ + public static JsonArray createEmptyArray() { + return Json.createArrayBuilder().build(); + } + + /** + * Creates empty JSON array after ADD STR_VALUE operation. + * + * @return Empty JSON array after ADD STR_VALUE operation. + */ + public static JsonArray createEmptyArrayWithStr() { + return Json.createArrayBuilder().add(STR_VALUE).build(); + } + + /** + * Creates empty JSON array after ADD INT_VALUE operation. + * + * @return Empty JSON array after ADD INT_VALUE operation. + */ + public static JsonArray createEmptyArrayWithInt() { + return Json.createArrayBuilder().add(INT_VALUE).build(); + } + + /** + * Creates empty JSON array after ADD BOOL_VALUE operation. + * + * @return Empty JSON array after ADD BOOL_VALUE operation. + */ + public static JsonArray createEmptyArrayWithBool() { + return Json.createArrayBuilder().add(BOOL_VALUE).build(); + } + + /** + * Creates empty JSON array after ADD OBJ_VALUE operation. + * + * @return Empty JSON array after ADD OBJ_VALUE operation. + */ + public static JsonArray createEmptyArrayWithObject() { + return Json.createArrayBuilder().add(OBJ_VALUE).build(); + } + + /** + * Creates simple JSON object. + * + * @return Simple JSON object. + */ + public static JsonObject createSimpleObject() { + return Json.createObjectBuilder().add(DEF_NAME, DEF_VALUE).build(); + } + + /** + * Creates simple JSON object after ADD STR_NAME STR_VALUE operation. + * + * @return Simple JSON object after ADD STR_NAME STR_VALUE operation. + */ + public static JsonObject createSimpleObjectWithStr() { + return Json.createObjectBuilder().add(DEF_NAME, DEF_VALUE) + .add(STR_NAME, STR_VALUE).build(); + } + + /** + * Creates simple JSON object after REPLACE STR_NAME STR_VALUE operation. + * + * @return Simple JSON object after REPLACE STR_NAME STR_VALUE operation. + */ + public static JsonObject createSimpleObjectReplaceStr() { + return Json.createObjectBuilder().add(STR_NAME, STR_VALUE2).build(); + } + + /** + * Creates simple JSON object after MOVE STR_NAME DEF_NAME operation. + * + * @return Simple JSON object after MOVE STR_NAME DEF_NAME operation. + */ + public static JsonObject createSimpleObjectMoveStr() { + return Json.createObjectBuilder().add(DEF_NAME, STR_VALUE).build(); + } + + /** + * Creates simple JSON object after COPY STR_NAME DEF_NAME operation. + * + * @return Simple JSON object after COPY STR_NAME DEF_NAME operation. + */ + public static JsonObject createSimpleObjectCopyStr() { + return Json.createObjectBuilder().add(STR_NAME, STR_VALUE) + .add(DEF_NAME, STR_VALUE).build(); + } + + /** + * Creates simple JSON object after ADD INT_NAME INT_VALUE operation. + * + * @return Simple JSON object after ADD INT_NAME INT_VALUE operation. + */ + public static JsonObject createSimpleObjectWithInt() { + return Json.createObjectBuilder().add(DEF_NAME, DEF_VALUE) + .add(INT_NAME, INT_VALUE).build(); + } + + /** + * Creates simple JSON object after REPLACE INT_NAME INT_VALUE operation. + * + * @return Simple JSON object after REPLACE INT_NAME INT_VALUE operation. + */ + public static JsonObject createSimpleObjectReplaceInt() { + return Json.createObjectBuilder().add(INT_NAME, INT_VALUE2).build(); + } + + /** + * Creates simple JSON object after MOVE INT_NAME DEF_NAME operation. + * + * @return Simple JSON object after MOVE INT_NAME DEF_NAME operation. + */ + public static JsonObject createSimpleObjectMoveInt() { + return Json.createObjectBuilder().add(DEF_NAME, INT_VALUE).build(); + } + + /** + * Creates simple JSON object after COPY INT_NAME DEF_NAME operation. + * + * @return Simple JSON object after COPY INT_NAME DEF_NAME operation. + */ + public static JsonObject createSimpleObjectCopyInt() { + return Json.createObjectBuilder().add(INT_NAME, INT_VALUE) + .add(DEF_NAME, INT_VALUE).build(); + } + + /** + * Creates simple JSON object after ADD BOOL_NAME BOOL_VALUE operation. + * + * @return Simple JSON object after ADD BOOL_NAME BOOL_VALUE operation. + */ + public static JsonObject createSimpleObjectWithBool() { + return Json.createObjectBuilder().add(DEF_NAME, DEF_VALUE) + .add(BOOL_NAME, BOOL_VALUE).build(); + } + + /** + * Creates simple JSON object after REPLACE BOOL_NAME BOOL_VALUE operation. + * + * @return Simple JSON object after REPLACE BOOL_NAME BOOL_VALUE operation. + */ + public static JsonObject createSimpleObjectReplaceBool() { + return Json.createObjectBuilder().add(BOOL_NAME, BOOL_VALUE2).build(); + } + + /** + * Creates simple JSON object after MOVE BOOL_NAME DEF_NAME operation. + * + * @return Simple JSON object after MOVE BOOL_NAME DEF_NAME operation. + */ + public static JsonObject createSimpleObjectMoveBool() { + return Json.createObjectBuilder().add(DEF_NAME, BOOL_VALUE).build(); + } + + /** + * Creates simple JSON object after COPY BOOL_NAME DEF_NAME operation. + * + * @return Simple JSON object after COPY BOOL_NAME DEF_NAME operation. + */ + public static JsonObject createSimpleObjectCopyBool() { + return Json.createObjectBuilder().add(BOOL_NAME, BOOL_VALUE) + .add(DEF_NAME, BOOL_VALUE).build(); + } + + /** + * Creates simple JSON object. + * + * @return Simple JSON object. + */ + public static JsonObject createCompoundObject() { + return Json.createObjectBuilder().add(DEF_NAME, DEF_VALUE) + .add(DEF_OBJ_NAME, DEF_OBJ_VALUE).build(); + } + + /** + * Creates simple JSON object after ADD OBJ_NAME OBJ_VALUE operation. + * + * @return Simple JSON object after ADD OBJ_NAME OBJ_VALUE operation. + */ + public static JsonObject createCompoundObjectWithObject() { + return Json.createObjectBuilder().add(DEF_NAME, DEF_VALUE) + .add(DEF_OBJ_NAME, DEF_OBJ_VALUE).add(OBJ_NAME, OBJ_VALUE).build(); + } + + /** + * Creates simple JSON object after ADD OBJ_NAME OBJ_VALUE operation. + * + * @return Simple JSON object after ADD OBJ_NAME OBJ_VALUE operation. + */ + public static JsonObject createCompoundObjectReplaceObject() { + return Json.createObjectBuilder().add(DEF_NAME, DEF_VALUE) + .add(DEF_OBJ_NAME, DEF_OBJ_VALUE).add(OBJ_NAME, OBJ_VALUE2).build(); + } + + /** + * Creates simple JSON object after MOVE DEF_PATH DEF_OBJ_PATH+DEF_PATH. + * + * @return Simple JSON object. + */ + public static JsonObject createCompoundObjectMoveValue() { + return Json.createObjectBuilder().add(DEF_OBJ_NAME, DEF_OBJ_VALUE2).build(); + } + + /** + * Creates simple JSON object after COPY DEF_PATH DEF_OBJ_PATH+DEF_PATH. + * + * @return Simple JSON object. + */ + public static JsonObject createCompoundObjectCopyValue() { + return Json.createObjectBuilder().add(DEF_NAME, DEF_VALUE) + .add(DEF_OBJ_NAME, DEF_OBJ_VALUE2).build(); + } + + /** + * Creates simple JSON object after MOVE OBJ_NAME DEF_NAME operation. + * + * @return Simple JSON object after MOVE OBJ_NAME DEF_NAME operation. + */ + public static JsonObject createSimpleObjectMoveObject() { + return Json.createObjectBuilder().add(DEF_NAME, OBJ_VALUE).build(); + } + + /** + * Creates simple JSON object after COPY OBJ_NAME DEF_NAME operation. + * + * @return Simple JSON object after COPY OBJ_NAME DEF_NAME operation. + */ + public static JsonObject createSimpleObjectCopyObject() { + return Json.createObjectBuilder().add(OBJ_NAME, OBJ_VALUE) + .add(DEF_NAME, OBJ_VALUE).build(); + } + + /** + * Creates compound JSON object after ADD DEF_OBJ_NAME, + * createSimpleStringArray5(). + * + * @return compound JSON object with ADD operation applied. + */ + public static JsonObject createCompoundObjectWithObjectReplaced() { + return Json.createObjectBuilder().add(DEF_NAME, DEF_VALUE) + .add(DEF_OBJ_NAME, createSimpleStringArray5()).build(); + } + + /** + * Creates simple JSON object with provided {@code name[i]} and + * {@code value[i]} pairs. + * + * @param names + * Names of JSON values to be added. Pairs of {@code names[i]} and + * {@code values[i]} are used for add operations. + * @param values + * JSON values to be added for specified names. + * @return Simple JSON object. + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonObject createSimpleObject(final String[] names, + final Object[] values) { + if (names.length != values.length) { + throw new IllegalArgumentException( + "Number of paths does not match number of indexes"); + } + JsonObjectBuilder builder = Json.createObjectBuilder(); + for (int i = 0; i < names.length; i++) { + switch (JsonValueType.getType(values[i].getClass())) { + case String: + builder = builder.add(names[i], (String) values[i]); + break; + case Integer: + builder = builder.add(names[i], ((Integer) values[i]).intValue()); + break; + case Boolean: + builder = builder.add(names[i], ((Boolean) values[i]).booleanValue()); + break; + case JsonValue: + builder = builder.add(names[i], (JsonValue) values[i]); + break; + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + return builder.build(); + } + + /** + * Creates simple JSON array with specified {@code String} values. + * + * @param values + * JSON array {@code String} values. + * @return Newly created JSON array. + */ + public static JsonArray createStringArray(final String... values) { + JsonArrayBuilder builder = Json.createArrayBuilder(); + if (values != null) { + for (final String value : values) { + builder = builder.add(value); + } + } + return builder.build(); + } + + /** + * Creates simple JSON array with single {@code String}. + * + * @return Newly created JSON array. + */ + public static JsonArray createStringArray1() { + return Json.createArrayBuilder().add(STR_VALUE_1).build(); + } + + /** + * Creates simple JSON array after ADD STR_VALUE operation before existing + * element. + * + * @return Simple JSON array after ADD STR_VALUE operation before existing + * element. + */ + public static JsonArray createSimpleStringArrayWithStrBefore() { + return Json.createArrayBuilder().add(STR_VALUE).add(STR_VALUE_1).build(); + } + + /** + * Creates simple JSON array after ADD STR_VALUE operation after existing + * element. + * + * @return Simple JSON array after ADD STR_VALUE operation after existing + * element. + */ + public static JsonArray createSimpleStringArrayWithStrAfter() { + return Json.createArrayBuilder().add(STR_VALUE_1).add(STR_VALUE).build(); + } + + /** + * Creates simple JSON array after REPLACE STR_VALUE operation on existing + * element. + * + * @return Simple JSON array after REPLACE STR_VALUE operation on existing + * element. + */ + public static JsonArray createSimpleStringArrayReplaceStr() { + return Json.createArrayBuilder().add(STR_VALUE).build(); + } + + /** + * Creates simple JSON array with two {@code String} values. + * + * @return Newly created JSON array. + */ + public static JsonArray createStringArray2() { + return Json.createArrayBuilder().add(STR_VALUE_2).add(STR_VALUE_4).build(); + } + + /** + * Creates simple JSON array with two {@code String} values in reversed order. + * + * @return Newly created JSON array. + */ + public static JsonArray createStringArray2R() { + return Json.createArrayBuilder().add(STR_VALUE_4).add(STR_VALUE_2).build(); + } + + /** + * Creates simple JSON array with two {@code String} values to be inserted + * into another array. + * + * @return Newly created JSON array. + */ + public static JsonArray createStringInnerArray2() { + return Json.createArrayBuilder().add(STR_VALUE_6).add(STR_VALUE_7).build(); + } + + /** + * Creates simple JSON array with three {@code String} values as a result of + * COPY 2nd element to the beginning of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createStringArray2Copy1to0() { + return Json.createArrayBuilder().add(STR_VALUE_4).add(STR_VALUE_2) + .add(STR_VALUE_4).build(); + } + + /** + * Creates simple JSON array with three {@code String} values as a result of + * COPY 1st element to the end of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createStringArray2Copy0to2() { + return Json.createArrayBuilder().add(STR_VALUE_2).add(STR_VALUE_4) + .add(STR_VALUE_2).build(); + } + + /** + * Creates simple JSON array with three {@code String} values as a result of + * COPY 1st element to the middle of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createStringArray2Copy0to1() { + return Json.createArrayBuilder().add(STR_VALUE_2).add(STR_VALUE_2) + .add(STR_VALUE_4).build(); + } + + /** + * Creates simple JSON array with five {@code String} values. + * + * @return Newly created JSON array. + */ + public static JsonArray createSimpleStringArray5() { + return Json.createArrayBuilder().add(STR_VALUE_1).add(STR_VALUE_2) + .add(STR_VALUE_3).add(STR_VALUE_4).add(STR_VALUE_5).build(); + } + + /** + * Creates simple JSON array with five {@code String} values in reversed + * order. + * + * @return Newly created JSON array. + */ + public static JsonArray createSimpleStringArray5R() { + return Json.createArrayBuilder().add(STR_VALUE_5).add(STR_VALUE_4) + .add(STR_VALUE_3).add(STR_VALUE_2).add(STR_VALUE_1).build(); + } + + /** + * Creates simple JSON array after ADD [STR_VALUE_6, STR_VALUE_7] operation + * between two existing elements. + * + * @return Simple JSON array after ADD operation. + */ + public static JsonArray createStringArray2WithStringArrayInTheMiddle() { + return Json.createArrayBuilder().add(STR_VALUE_2) + .add(createStringInnerArray2()).add(STR_VALUE_4).build(); + } + + /** + * Creates simple JSON array with single {@code int}. + * + * @return Newly created JSON array. + */ + public static JsonArray createIntArray1() { + return Json.createArrayBuilder().add(INT_VALUE_1).build(); + } + + /** + * Creates simple JSON array after ADD INT_VALUE operation before existing + * element. + * + * @return Simple JSON array after ADD INT_VALUE operation before existing + * element. + */ + public static JsonArray createSimpleIntArrayWithIntBefore() { + return Json.createArrayBuilder().add(INT_VALUE).add(INT_VALUE_1).build(); + } + + /** + * Creates simple JSON array after ADD INT_VALUE operation after existing + * element. + * + * @return Simple JSON array after ADD INT_VALUE operation after existing + * element. + */ + public static JsonArray createSimpleIntArrayWithIntAfter() { + return Json.createArrayBuilder().add(INT_VALUE_1).add(INT_VALUE).build(); + } + + /** + * Creates simple JSON array after REPLACE INT_VALUE operation on existing + * element. + * + * @return Simple JSON array after REPLACE INT_VALUE operation on existing + * element. + */ + public static JsonArray createSimpleIntArrayReplaceInt() { + return Json.createArrayBuilder().add(INT_VALUE).build(); + } + + /** + * Creates simple JSON array with two {@code int} values. + * + * @return Newly created JSON array. + */ + public static JsonArray createIntArray2() { + return Json.createArrayBuilder().add(INT_VALUE_2).add(INT_VALUE_4).build(); + } + + /** + * Creates simple JSON array with two {@code int} values in reversed order. + * + * @return Newly created JSON array. + */ + public static JsonArray createIntArray2R() { + return Json.createArrayBuilder().add(INT_VALUE_4).add(INT_VALUE_2).build(); + } + + /** + * Creates simple JSON array with three {@code int} values as a result of COPY + * 2nd element to the beginning of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createIntArray2Copy1to0() { + return Json.createArrayBuilder().add(INT_VALUE_4).add(INT_VALUE_2) + .add(INT_VALUE_4).build(); + } + + /** + * Creates simple JSON array with three {@code int} values as a result of COPY + * 1st element to the end of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createIntArray2Copy0to2() { + return Json.createArrayBuilder().add(INT_VALUE_2).add(INT_VALUE_4) + .add(INT_VALUE_2).build(); + } + + /** + * Creates simple JSON array with three {@code int} values as a result of COPY + * 1st element to the middle of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createIntArray2Copy0to1() { + return Json.createArrayBuilder().add(INT_VALUE_2).add(INT_VALUE_2) + .add(INT_VALUE_4).build(); + } + + /** + * Creates simple JSON array with five {@code int} values. + * + * @return Newly created JSON array. + */ + public static JsonArray createSimpleIntArray5() { + return Json.createArrayBuilder().add(INT_VALUE_1).add(INT_VALUE_2) + .add(INT_VALUE_3).add(INT_VALUE_4).add(INT_VALUE_5).build(); + } + + /** + * Creates simple JSON array with five {@code int} values in reversed order. + * + * @return Newly created JSON array. + */ + public static JsonArray createSimpleIntArray5R() { + return Json.createArrayBuilder().add(INT_VALUE_5).add(INT_VALUE_4) + .add(INT_VALUE_3).add(INT_VALUE_2).add(INT_VALUE_1).build(); + } + + /** + * Creates simple JSON array with single {@code boolean}. + * + * @return Newly created JSON array. + */ + public static JsonArray createBoolArray1() { + return Json.createArrayBuilder().add(BOOL_TRUE).build(); + } + + /** + * Creates simple JSON array after ADD BOOL_FALSE operation before existing + * element (BOOL_TRUE). + * + * @return Simple JSON array after ADD BOOL_FALSE operation before existing + * element. + */ + public static JsonArray createSimpleBoolArrayWithBoolBefore() { + return Json.createArrayBuilder().add(BOOL_FALSE).add(BOOL_TRUE).build(); + } + + /** + * Creates simple JSON array after ADD BOOL_FALSE operation after existing + * element (BOOL_TRUE). + * + * @return Simple JSON array after ADD BOOL_FALSE operation after existing + * element. + */ + public static JsonArray createSimpleBoolArrayWithBoolAfter() { + return Json.createArrayBuilder().add(BOOL_TRUE).add(BOOL_FALSE).build(); + } + + /** + * Creates simple JSON array after REPLACE BOOL_FALSE operation on existing + * element. + * + * @return Simple JSON array after REPLACE BOOL_FALSE operation on existing + * element. + */ + public static JsonArray createSimpleBoolArrayReplaceBool() { + return Json.createArrayBuilder().add(BOOL_FALSE).build(); + } + + /** + * Creates simple JSON array with two {@code boolean} values. + * + * @return Newly created JSON array. + */ + public static JsonArray createBoolArray2() { + return Json.createArrayBuilder().add(BOOL_TRUE).add(BOOL_FALSE).build(); + } + + /** + * Creates simple JSON array with two {@code boolean} values in reverse order. + * + * @return Newly created JSON array. + */ + public static JsonArray createBoolArray2R() { + return Json.createArrayBuilder().add(BOOL_FALSE).add(BOOL_TRUE).build(); + } + + /** + * Creates simple JSON array with three {@code boolean} values as a result of + * COPY 2nd element to the beginning of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createBoolArray2Copy1to0() { + return Json.createArrayBuilder().add(BOOL_FALSE).add(BOOL_TRUE) + .add(BOOL_FALSE).build(); + } + + /** + * Creates simple JSON array with three {@code boolean} values as a result of + * COPY 1st element to the end of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createBoolArray2Copy0to2() { + return Json.createArrayBuilder().add(BOOL_TRUE).add(BOOL_FALSE) + .add(BOOL_TRUE).build(); + } + + /** + * Creates simple JSON array with three {@code boolean} values as a result of + * COPY 1st element to the middle of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createBoolArray2Copy0to1() { + return Json.createArrayBuilder().add(BOOL_TRUE).add(BOOL_TRUE) + .add(BOOL_FALSE).build(); + } + + /** + * Creates simple JSON array with five {@code boolean} values. + * + * @return Newly created JSON array. + */ + public static JsonArray createSimpleBoolArray5() { + return Json.createArrayBuilder().add(BOOL_FALSE).add(BOOL_TRUE) + .add(BOOL_TRUE).add(BOOL_FALSE).add(BOOL_TRUE).build(); + } + + /** + * Creates simple JSON array with five {@code boolean} values in reversed + * order. + * + * @return Newly created JSON array. + */ + public static JsonArray createSimpleBoolArray5R() { + return Json.createArrayBuilder().add(BOOL_TRUE).add(BOOL_FALSE) + .add(BOOL_TRUE).add(BOOL_TRUE).add(BOOL_FALSE).build(); + } + + /** + * Creates simple JSON array with single {@code JsonObject}. + * + * @return Newly created JSON array. + */ + public static JsonArray createObjectArray1() { + return Json.createArrayBuilder().add(OBJ_VALUE_1).build(); + } + + /** + * Creates simple JSON array after ADD OBJ_VALUE operation before existing + * element. + * + * @return Simple JSON array after ADD OBJ_VALUE operation before existing + * element. + */ + public static JsonArray createSimpleObjectArrayWithObjectBefore() { + return Json.createArrayBuilder().add(OBJ_VALUE).add(OBJ_VALUE_1).build(); + } + + /** + * Creates simple JSON array after ADD OBJ_VALUE operation after existing + * element. + * + * @return Simple JSON array after ADD OBJ_VALUE operation after existing + * element. + */ + public static JsonArray createSimpleObjectArrayWithObjectAfter() { + return Json.createArrayBuilder().add(OBJ_VALUE_1).add(OBJ_VALUE).build(); + } + + /** + * Creates simple JSON array after REPLACE OBJ_VALUE operation on existing + * element. + * + * @return Simple JSON array after REPLACE OBJ_VALUE operation on existing + * element. + */ + public static JsonArray createSimpleObjectArrayReplaceObject() { + return Json.createArrayBuilder().add(OBJ_VALUE).build(); + } + + /** + * Creates simple JSON array with two {@code JsonObject} values. + * + * @return Newly created JSON array. + */ + public static JsonArray createObjectArray2() { + return Json.createArrayBuilder().add(OBJ_VALUE_2).add(OBJ_VALUE_4).build(); + } + + /** + * Creates simple JSON array with two {@code JsonObject} values in reverse + * order. + * + * @return Newly created JSON array. + */ + public static JsonArray createObjectArray2R() { + return Json.createArrayBuilder().add(OBJ_VALUE_4).add(OBJ_VALUE_2).build(); + } + + /** + * Creates simple JSON array with three {@code JsonObject} values as a result + * of COPY 2nd element to the beginning of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createObjectArray2Copy1to0() { + return Json.createArrayBuilder().add(OBJ_VALUE_4).add(OBJ_VALUE_2) + .add(OBJ_VALUE_4).build(); + } + + /** + * Creates simple JSON array with three {@code JsonObject} values as a result + * of COPY 1st element to the end of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createObjectArray2Copy0to2() { + return Json.createArrayBuilder().add(OBJ_VALUE_2).add(OBJ_VALUE_4) + .add(OBJ_VALUE_2).build(); + } + + /** + * Creates simple JSON array with three {@code JsonObject} values as a result + * of COPY 1st element to the middle of the array. + * + * @return Newly created JSON array. + */ + public static JsonArray createObjectArray2Copy0to1() { + return Json.createArrayBuilder().add(OBJ_VALUE_2).add(OBJ_VALUE_2) + .add(OBJ_VALUE_4).build(); + } + + /** + * Creates simple JSON array with five {@code JsonObject} values. + * + * @return Newly created JSON array. + */ + public static JsonArray createSimpleObjectArray5() { + return Json.createArrayBuilder().add(OBJ_VALUE_1).add(OBJ_VALUE_2) + .add(OBJ_VALUE_3).add(OBJ_VALUE_4).add(OBJ_VALUE_5).build(); + } + + /** + * Creates simple JSON array with five {@code JsonObject} values in reversed + * order. + * + * @return Newly created JSON array. + */ + public static JsonArray createSimpleObjectArray5R() { + return Json.createArrayBuilder().add(OBJ_VALUE_5).add(OBJ_VALUE_4) + .add(OBJ_VALUE_3).add(OBJ_VALUE_2).add(OBJ_VALUE_1).build(); + } + + /** + * Convert provided {@code Object} instance to {@code JsonValue}. + * + * @param value + * {@code Object} instance to be converted. + * @return JsonValue instance containing provided {@code Object}; + */ + @SuppressWarnings("UnnecessaryUnboxing") + public static JsonValue toJsonValue(final Object value) { + if (value == null) { + return JsonValue.NULL; + } + switch (JsonValueType.getType(value.getClass())) { + case String: + return Json.createValue((String) value); + case Integer: + return Json.createValue(((Integer) value).intValue()); + case Long: + return Json.createValue(((Long) value).longValue()); + case BigInteger: + return Json.createValue((BigInteger) value); + case Double: + return Json.createValue(((Double) value).doubleValue()); + case BigDecimal: + return Json.createValue((BigDecimal) value); + case Boolean: + return ((Boolean) value).booleanValue() ? JsonValue.TRUE + : JsonValue.FALSE; + case JsonValue: + return (JsonValue) value; + case Null: + return JsonValue.NULL; + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + + /** + * Convert JSON value to {@code String} containing value stored in JSON + * format. + * + * @param value + * JSON value to be converted. + * @return Provided value stored in JSON format. + */ + public static String jsonData(final JsonValue value) { + final StringWriter strWriter = new StringWriter(); + try (final JsonWriter writer = Json.createWriter(strWriter)) { + writer.write(value); + } catch (JsonException ex) { + System.out.println( + "Could not initialize JSON data: " + ex.getLocalizedMessage()); + throw ex; + } + return strWriter.toString(); + } + + /** + * Apply patch on provided JSON {@code value} using {@code apply()} method of + * {@code JsonPatch}. + * + * @param patch + * {@code JsonPatch} with patch operations. + * @param value + * JSON {@code value} to be patched. + * @return Result of JSON {@code value} patching. + */ + public static JsonValue patchApply(final JsonPatch patch, + final JsonValue value) { + switch (value.getValueType()) { + case OBJECT: + return patch.apply((JsonObject) value); + case ARRAY: + return patch.apply((JsonArray) value); + default: + throw new IllegalArgumentException( + "Unsupported JSON value type to be pached"); + } + } + + /** + * Convert {@code boolean} value to {@code JsonValue}. + * + * @param value + * Source {@code boolean} value. + * @return {@code JsonValue.TRUE} if provided {@code value} is {@code true} or + * {@code JsonValue.FALSE} otherwise. + */ + public static JsonValue booleanValue(final boolean value) { + return value ? JsonValue.TRUE : JsonValue.FALSE; + } + + /** + * Creates an instance of RFC 6902 operation test. + */ + private SimpleValues() { + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/TestFail.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/TestFail.java new file mode 100644 index 0000000..630c286 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/TestFail.java
@@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +/** + * Test failure notification. + */ +public class TestFail { + + /** Test failure name and message separator. */ + private static final String NM_SEP = ": "; + + /** Name of test that failed. */ + private final String name; + + /** Error message. */ + private final String message; + + /** + * Creates an instance of test failure notification. + * + * @param name + * Test name. + * @param message + * Error message. + */ + public TestFail(final String name, final String message) { + this.name = name; + this.message = message; + } + + /** + * Returns human readable content of test failure notification. + * + * @return Human readable content of test failure notification. + */ + @Override + public String toString() { + final StringBuilder sb = new StringBuilder( + name.length() + message.length() + NM_SEP.length()); + sb.append(name); + sb.append(NM_SEP); + sb.append(message); + return sb.toString(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/TestResult.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/TestResult.java new file mode 100644 index 0000000..69309f2 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/common/TestResult.java
@@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.common; + +import jakarta.jsonp.tck.api.common.TestFail; +import jakarta.jsonp.tck.lib.harness.Fault; + +import java.util.LinkedList; + +/** + * Tests result record. + */ +public class TestResult { + + /** Name of test suite. */ + private final String name; + + /** List of test failures. */ + private final LinkedList<TestFail> fails; + + /** + * Creates an instance of tests result record. + * + * @param name + * Name of test suite. + */ + public TestResult(final String name) { + this.name = name; + this.fails = new LinkedList<>(); + } + + /** + * Records test failure. + * + * @param name + * Test name. + * @param message + * Error message. + */ + public void fail(final String name, final String message) { + fails.addLast(new TestFail(name, message)); + } + + /** + * Evaluate test results. + * + * @throws Fault + * when any test failed. + */ + public void eval() throws Fault { + if (fails.isEmpty()) { + return; + } + final StringBuilder sb = new StringBuilder(); + sb.append(name); + sb.append(" failed:"); + for (TestFail fail : fails) { + sb.append('\n'); + sb.append(fail.toString()); + } + throw new Fault(sb.toString()); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/exceptiontests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/exceptiontests/ClientTests.java new file mode 100644 index 0000000..4ee38c9 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/exceptiontests/ClientTests.java
@@ -0,0 +1,292 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.exceptiontests; + +import jakarta.json.*; +import jakarta.json.stream.*; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + + /* Tests */ + + /* + * @testName: jsonExceptionConstructorTest1 + * + * @assertion_ids: JSONP:JAVADOC:37; + * + * @test_Strategy: Test API: JsonException ret = new JsonException(String) + */ + @Test + public void jsonExceptionConstructorTest1() throws Fault { + boolean pass = true; + + try { + String message = "This JSON is incorrect."; + + System.out.println("Test JsonException(String)"); + JsonException exception = new JsonException(message); + try { + throw exception; + } catch (JsonException e) { + if (!e.getMessage().equals(message)) { + System.err.println("Incorrect message: expected " + message + ", received " + + e.getMessage()); + pass = false; + } + } + } catch (Exception e) { + throw new Fault("jsonExceptionConstructorTest1 Failed: ", e); + } + + if (!pass) + throw new Fault("jsonExceptionConstructorTest1 Failed:"); + } + + /* + * @testName: jsonExceptionConstructorTest2 + * + * @assertion_ids: JSONP:JAVADOC:38; + * + * @test_Strategy: Test API: JsonException ret = new JsonException(String, + * Throwable) + */ + @Test + public void jsonExceptionConstructorTest2() throws Fault { + boolean pass = true; + + try { + String message = "This JSON is incorrect due to foo."; + Exception foo = new Exception("This is a foo exception"); + + System.out.println("Test JsonException(String, Throwable)"); + JsonException exception = new JsonException(message, foo); + + try { + throw exception; + } catch (JsonException e) { + if (!e.getCause().equals(foo)) { + System.err.println("Incorrect cause: expected " + foo + ", received " + + e.getCause()); + pass = false; + } + if (!e.getMessage().equals(message)) { + System.err.println("Incorrect message: expected " + message + ", received " + + e.getMessage()); + pass = false; + } + } + + } catch (Exception e) { + throw new Fault("jsonExceptionConstructorTest2 Failed: ", e); + } + + if (!pass) + throw new Fault("jsonExceptionConstructorTest2 Failed:"); + } + + /* + * @testName: jsonParsingExceptionConstructorTest1 + * + * @assertion_ids: JSONP:JAVADOC:285; JSONP:JAVADOC:478; JSONP:JAVADOC:474; + * JSONP:JAVADOC:475; JSONP:JAVADOC:476; + * + * @test_Strategy: Test API: JsonParsingException ret = new + * JsonParsingException(String, JsonLocation) + */ + @Test + public void jsonParsingExceptionConstructorTest1() throws Fault { + boolean pass = true; + + try { + String message = "This JSON is incorrect."; + MyJsonLocation expLoc = new MyJsonLocation(10, 20, 30); + System.out.println("MyJsonLocation"); + JSONP_Util.dumpLocation(expLoc); + + System.out.println("Test JsonParsingException(String, JsonLocation)"); + JsonParsingException exception = new JsonParsingException(message, + expLoc); + try { + throw exception; + } catch (JsonParsingException e) { + if (!e.getMessage().equals(message)) { + System.err.println("Incorrect message: expected " + message + ", received " + + e.getMessage()); + pass = false; + } + } + JsonLocation actLoc = exception.getLocation(); + System.out.println("JsonParsingException.getLocation()"); + JSONP_Util.dumpLocation(actLoc); + if (!JSONP_Util.assertEquals(expLoc, actLoc)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonParsingExceptionConstructorTest1 Failed: ", e); + } + + if (!pass) + throw new Fault("jsonParsingExceptionConstructorTest1 Failed:"); + } + + /* + * @testName: jsonParsingExceptionConstructorTest2 + * + * @assertion_ids: JSONP:JAVADOC:286; JSONP:JAVADOC:478; JSONP:JAVADOC:474; + * JSONP:JAVADOC:475; JSONP:JAVADOC:476; + * + * @test_Strategy: Test API: JsonParsingException ret = new + * JsonParsingException(String, Throwable, JsonLocation) + */ + @Test + public void jsonParsingExceptionConstructorTest2() throws Fault { + boolean pass = true; + + try { + String message = "This JSON is incorrect due to foo."; + Exception foo = new Exception("This is a foo exception"); + MyJsonLocation expLoc = new MyJsonLocation(10, 20, 30); + System.out.println("MyJsonLocation"); + JSONP_Util.dumpLocation(expLoc); + + System.out.println("Test JsonParsingException(String, Throwable)"); + JsonParsingException exception = new JsonParsingException(message, foo, + expLoc); + + try { + throw exception; + } catch (JsonParsingException e) { + if (!e.getCause().equals(foo)) { + System.err.println("Incorrect cause: expected " + foo + ", received " + + e.getCause()); + pass = false; + } + if (!e.getMessage().equals(message)) { + System.err.println("Incorrect message: expected " + message + ", received " + + e.getMessage()); + pass = false; + } + } + JsonLocation actLoc = exception.getLocation(); + System.out.println("JsonParsingException.getLocation()"); + JSONP_Util.dumpLocation(actLoc); + if (!JSONP_Util.assertEquals(expLoc, actLoc)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonParsingExceptionConstructorTest2 Failed: ", e); + } + + if (!pass) + throw new Fault("jsonParsingExceptionConstructorTest2 Failed:"); + } + + /* + * @testName: jsonGenerationExceptionConstructorTest1 + * + * @assertion_ids: JSONP:JAVADOC:278; + * + * @test_Strategy: Test API: JsonGenerationException ret = new + * JsonGenerationException(String) + */ + @Test + public void jsonGenerationExceptionConstructorTest1() throws Fault { + boolean pass = true; + + try { + String message = "This JSON is incorrect."; + + System.out.println("Test JsonGenerationException(String)"); + JsonGenerationException exception = new JsonGenerationException(message); + try { + throw exception; + } catch (JsonGenerationException e) { + if (!e.getMessage().equals(message)) { + System.err.println("Incorrect message: expected " + message + ", received " + + e.getMessage()); + pass = false; + } + } + } catch (Exception e) { + throw new Fault("jsonGenerationExceptionConstructorTest1 Failed: ", e); + } + + if (!pass) + throw new Fault("jsonGenerationExceptionConstructorTest1 Failed:"); + } + + /* + * @testName: jsonGenerationExceptionConstructorTest2 + * + * @assertion_ids: JSONP:JAVADOC:279; + * + * @test_Strategy: Test API: JsonGenerationException ret = new + * JsonGenerationException(String, Throwable) + */ + @Test + public void jsonGenerationExceptionConstructorTest2() throws Fault { + boolean pass = true; + + try { + String message = "This JSON is incorrect due to foo."; + Exception foo = new Exception("This is a foo exception"); + + System.out.println("Test JsonGenerationException(String, Throwable)"); + JsonGenerationException exception = new JsonGenerationException(message, + foo); + + try { + throw exception; + } catch (JsonGenerationException e) { + if (!e.getCause().equals(foo)) { + System.err.println("Incorrect cause: expected " + foo + ", received " + + e.getCause()); + pass = false; + } + if (!e.getMessage().equals(message)) { + System.err.println("Incorrect message: expected " + message + ", received " + + e.getMessage()); + pass = false; + } + } + + } catch (Exception e) { + throw new Fault("jsonGenerationExceptionConstructorTest2 Failed: ", e); + } + + if (!pass) + throw new Fault("jsonGenerationExceptionConstructorTest2 Failed:"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuildAdd.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuildAdd.java new file mode 100644 index 0000000..3c6f463 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuildAdd.java
@@ -0,0 +1,618 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonarraytests; + +import jakarta.jsonp.tck.api.common.ArrayBuilder; +import jakarta.jsonp.tck.api.common.JsonIO; +import jakarta.jsonp.tck.api.common.JsonValueType; +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests: + * {@link JsonArrayBuilder} API add() methods added in JSON-P 1.1.<br> + */ +public class ArrayBuildAdd extends ArrayCommon { + + /** + * Creates an instance of {@link JsonArrayBuilder} API add() methods added in + * JSON-P 1.1 test. + */ + ArrayBuildAdd() { + super(); + } + + /** + * Test {@link JsonArrayBuilder} API add() methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonArrayBuilder API add() methods added in JSON-P 1.1."); + System.out.println("JsonArrayBuilder API add() methods added in JSON-P 1.1."); + testAdd(result); + testAddNullBuilder(result); + testAddOutOfBounds(result); + testAddNull(result); + testAddNullOutOfBounds(result); + testAddArrayBuilder(result); + testAddArrayBuilderNull(result); + testAddArrayBuilderOutOfBounds(result); + testAddObjectBuilder(result); + testAddObjectBuilderNull(result); + testAddObjectBuilderOutOfBounds(result); + testAddAllString(result); + testAddAllInt(result); + testAddAllBool(result); + testAddAllObject(result); + testAddAllNull(result); + return result; + } + + /** + * Test {@code default JsonArrayBuilder add(int, Object)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testAdd(final TestResult result) { + final Object[] values = new Object[] { OBJ_VALUE, // add(int,JsonValue) + STR_VALUE, // add(int,String) + INT_VALUE, // add(int,int) + LNG_VALUE, // add(int,long) + DBL_VALUE, // add(int,double) + BIN_VALUE, // add(int,BigInteger) + BDC_VALUE, // add(int,BigDecimal) + BOOL_VALUE // add(int,boolean) + }; + for (Object value : values) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println(" - add(int," + typeName + ")"); + final String json = "[" + JsonValueType.toStringValue(value) + "]"; + final JsonValue check = JsonIO.read(json); + final JsonArrayBuilder builder = createArrayBuilder(0, value); + final JsonValue out = builder.build(); + if (operationFailed(check, out)) { + result.fail("add(" + typeName + ")", "Builder output " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + } + + /** + * Test {@code JsonArrayBuilder add(int, Object)} method on {@code String} + * array with index being out of range + * ({@code index < 0 || index > array size}). + * + * @param result + * Test suite result. + */ + private void testAddOutOfBounds(final TestResult result) { + final Object[] values = new Object[] { OBJ_VALUE, // add(int,JsonValue) + STR_VALUE, // add(int,String) + INT_VALUE, // add(int,int) + LNG_VALUE, // add(int,long) + DBL_VALUE, // add(int,double) + BIN_VALUE, // add(int,BigInteger) + BDC_VALUE, // add(int,BigDecimal) + BOOL_VALUE // add(int,boolean) + }; + final int[] indexes = new int[] { -1, 2, 3 }; + for (Object value : values) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println(" - add(int," + typeName + ")"); + final String json = "[" + JsonValueType.toStringValue(value) + "]"; + // Add value into the array for the first time to het array of size 1. + JsonArrayBuilder builder = createArrayBuilder(value); + for (int index : indexes) { + try { + // Add value on out of bounds index + builder = updateOperationBuilder(builder, index, value); + result.fail("add(int," + typeName + ")", + "Calling method with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println(" - Expected exception for index=" + index + ": " + + e.getMessage()); + } catch (Throwable t) { + result.fail("add(int,(" + typeName + ")null)", + "Calling method with with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException, not " + + t.getClass().getSimpleName()); + } + } + } + } + + /** + * Test {@code JsonArrayBuilder add(int, Object)} method on {@code String} + * array with null value. + * + * @param result + * Test suite result. + */ + private void testAddNullBuilder(final TestResult result) { + final JsonValueType[] types = new JsonValueType[] { JsonValueType.JsonValue, // add(int,(JsonValue)null) + JsonValueType.String, // add(int,(String)null) + JsonValueType.BigInteger, // add(int,(BigInteger)null) + JsonValueType.BigDecimal // add(int,(BigDecimal)null) + }; + for (JsonValueType type : types) { + final String typeName = type.name(); + System.out.println(" - add(int,(" + typeName + ")null)"); + try { + ArrayBuilder.add(Json.createArrayBuilder(), 0, type); + result.fail("add(int,(" + typeName + ")null)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("add(int,(" + typeName + ")null)", + "Calling method with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonArrayBuilder addNull(int)} method on {@code String} array. + * + * @param result + * Test suite result. + */ + private void testAddNull(final TestResult result) { + System.out.println(" - addNull(int)"); + final Object value = null; + final String json = "[" + JsonValueType.toStringValue(value) + "]"; + final JsonValue check = JsonIO.read(json); + final JsonArrayBuilder builder = createArrayBuilder(0, value); + final JsonValue out = builder.build(); + if (operationFailed(check, out)) { + result.fail("addNull(int)", "Builder output " + valueToString(out) + + " value shall be " + valueToString(check)); + } + } + + /** + * Test {@code JsonArrayBuilder addNull(int)} method on {@code String} array + * with index being out of range ({@code index < 0 || index > array size}). + * + * @param result + * Test suite result. + */ + private void testAddNullOutOfBounds(final TestResult result) { + final int[] indexes = new int[] { -1, 2, 3 }; + System.out.println(" - addNull(int)"); + final Object value = null; + JsonArrayBuilder builder = createArrayBuilder(value); + for (int index : indexes) { + try { + // Add value on out of bounds index + builder = updateOperationBuilder(builder, index, value); + result.fail("addNull(int)", "Calling method with out of bounds index=" + + index + " argument shall throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println(" - Expected exception for index=" + index + ": " + + e.getMessage()); + } catch (Throwable t) { + result.fail("addNull(int)", + "Calling method with with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonArrayBuilder add(int,JsonArrayBuilder)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testAddArrayBuilder(final TestResult result) { + System.out.println(" - add(int,JsonArrayBuilder)"); + final JsonValue checkBeg = JsonIO + .read("[[" + JsonValueType.toStringValue(STR_VALUE_1) + "," + + JsonValueType.toStringValue(STR_VALUE_2) + "," + + JsonValueType.toStringValue(STR_VALUE_3) + "," + + JsonValueType.toStringValue(STR_VALUE_4) + "]," + + JsonValueType.toStringValue(STR_VALUE_5) + "]"); + final JsonValue checkEnd = JsonIO + .read("[" + JsonValueType.toStringValue(STR_VALUE_1) + ",[" + + JsonValueType.toStringValue(STR_VALUE_2) + "," + + JsonValueType.toStringValue(STR_VALUE_3) + "," + + JsonValueType.toStringValue(STR_VALUE_4) + "," + + JsonValueType.toStringValue(STR_VALUE_5) + "]]"); + final JsonArrayBuilder inBeg = createArrayBuilder(STR_VALUE_5); + final JsonArrayBuilder inEnd = createArrayBuilder(STR_VALUE_1); + final JsonArrayBuilder argBeg = createArrayBuilder(STR_VALUE_1) + .add(STR_VALUE_2).add(STR_VALUE_3).add(STR_VALUE_4); + final JsonArrayBuilder argEnd = createArrayBuilder(STR_VALUE_2) + .add(STR_VALUE_3).add(STR_VALUE_4).add(STR_VALUE_5); + verifyAddBuilder(result, checkBeg, 0, argBeg, inBeg); + verifyAddBuilder(result, checkEnd, 1, argEnd, inEnd); + } + + /** + * Test {@code JsonArrayBuilder add(int,(JsonArrayBuilder)null)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testAddArrayBuilderNull(final TestResult result) { + System.out.println(" - add(int,(JsonArrayBuilder)null)"); + final JsonArrayBuilder in = createArrayBuilder(DEF_VALUE); + final JsonArrayBuilder arg = null; + try { + in.add(0, arg); + result.fail("add(int,(JsonArrayBuilder)null)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("add(int,(JsonArrayBuilder)null)", + "Calling method with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Test {@code JsonArrayBuilder add(int,JsonArrayBuilder)} method on + * {@code String} array with index being out of range + * ({@code index < 0 || index > array size}). + * + * @param result + * Test suite result. + */ + private void testAddArrayBuilderOutOfBounds(final TestResult result) { + System.out.println(" - add(int,JsonArrayBuilder)"); + final int[] indexes = new int[] { -1, 5, 6 }; + final JsonArrayBuilder in = createArrayBuilder(STR_VALUE_1).add(STR_VALUE_2) + .add(STR_VALUE_3).add(STR_VALUE_4); + final JsonArrayBuilder arg = createArrayBuilder(STR_VALUE_5); + for (int index : indexes) { + try { + // Add value on out of bounds index + in.add(index, arg); + result.fail("add(int,JsonArrayBuilder)", + "Calling method with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println(" - Expected exception for index=" + index + ": " + + e.getMessage()); + } catch (Throwable t) { + result.fail("add(int,JsonArrayBuilder)", + "Calling method with with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonArrayBuilder add(int,JsonObjectBuilder)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testAddObjectBuilder(final TestResult result) { + System.out.println(" - add(int,JsonObjectBuilder)"); + final JsonValue checkBeg = JsonIO + .read("[{" + JsonValueType.toStringValue(STR_NAME) + ":" + + JsonValueType.toStringValue(STR_VALUE) + "}," + + JsonValueType.toStringValue(STR_VALUE_1) + "]"); + final JsonValue checkEnd = JsonIO + .read("[" + JsonValueType.toStringValue(STR_VALUE_1) + ",{" + + JsonValueType.toStringValue(STR_NAME) + ":" + + JsonValueType.toStringValue(STR_VALUE) + "}]"); + final JsonArrayBuilder inBeg = createArrayBuilder(STR_VALUE_1); + final JsonArrayBuilder inEnd = createArrayBuilder(STR_VALUE_1); + final JsonObjectBuilder argBeg = Json.createObjectBuilder().add(STR_NAME, + STR_VALUE); + final JsonObjectBuilder argEnd = Json.createObjectBuilder().add(STR_NAME, + STR_VALUE); + verifyAddBuilder(result, checkBeg, 0, argBeg, inBeg); + verifyAddBuilder(result, checkEnd, 1, argEnd, inEnd); + } + + /** + * Test {@code JsonArrayBuilder add(int,(JsonObjectBuilder)null)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testAddObjectBuilderNull(final TestResult result) { + System.out.println(" - add(int,(JsonObjectBuilder)null)"); + final JsonArrayBuilder in = createArrayBuilder(DEF_VALUE); + final JsonObjectBuilder arg = null; + try { + in.add(0, arg); + result.fail("add(int,(JsonObjectBuilder)null)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("add(int,(JsonObjectBuilder)null)", + "Calling method with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Test {@code JsonArrayBuilder add(int,JsonObjectBuilder)} method on + * {@code String} array with index being out of range + * ({@code index < 0 || index > array size}). + * + * @param result + * Test suite result. + */ + private void testAddObjectBuilderOutOfBounds(final TestResult result) { + System.out.println(" - add(int,JsonObjectBuilder)"); + final int[] indexes = new int[] { -1, 5, 6 }; + final JsonArrayBuilder in = createArrayBuilder(STR_VALUE_1).add(STR_VALUE_2) + .add(STR_VALUE_3).add(STR_VALUE_4); + final JsonObjectBuilder arg = Json.createObjectBuilder().add(STR_NAME, + STR_VALUE); + for (int index : indexes) { + try { + // Add value on out of bounds index + in.add(index, arg); + result.fail("add(int,JsonObjectBuilder)", + "Calling method with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println(" - Expected exception for index=" + index + ": " + + e.getMessage()); + } catch (Throwable t) { + result.fail("add(int,JsonObjectBuilder)", + "Calling method with with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonArrayBuilder addAll(JsonArrayBuilder)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testAddAllString(final TestResult result) { + System.out.println(" - addAll(JsonArrayBuilder) for String array"); + final JsonArray check = createSimpleStringArray5(); + final String[] strings = new String[] { STR_VALUE_1, STR_VALUE_2, + STR_VALUE_3, STR_VALUE_4, STR_VALUE_5 }; + verifyAddAll(result, check, strings); + } + + /** + * Test {@code JsonArrayBuilder addAll(JsonArrayBuilder)} method on + * {@code int) array. @param result Test suite result. + */ + private void testAddAllInt(final TestResult result) { + System.out.println(" - addAll(JsonArrayBuilder) for int array"); + final JsonArray check = createSimpleIntArray5(); + final Integer[] ints = new Integer[] { INT_VALUE_1, INT_VALUE_2, + INT_VALUE_3, INT_VALUE_4, INT_VALUE_5 }; + verifyAddAll(result, check, ints); + } + + /** + * Test {@code JsonArrayBuilder addAll(JsonArrayBuilder)} method on + * {@code boolean) array. @param result Test suite result. + */ + private void testAddAllBool(final TestResult result) { + System.out.println(" - addAll(JsonArrayBuilder) for boolean array"); + final JsonArray check = createSimpleBoolArray5(); + final Boolean[] bools = new Boolean[] { BOOL_FALSE, BOOL_TRUE, BOOL_TRUE, + BOOL_FALSE, BOOL_TRUE }; + verifyAddAll(result, check, bools); + } + + /** + * Test {@code JsonArrayBuilder addAll(JsonArrayBuilder)} method on + * {@code JsonObject) array. @param result Test suite result. + */ + private void testAddAllObject(final TestResult result) { + System.out.println(" - addAll(JsonArrayBuilder) for JsonObject array"); + final JsonArray check = createSimpleObjectArray5(); + final JsonObject[] bools = new JsonObject[] { OBJ_VALUE_1, OBJ_VALUE_2, + OBJ_VALUE_3, OBJ_VALUE_4, OBJ_VALUE_5 }; + verifyAddAll(result, check, bools); + } + + /** + * Test {@code JsonArrayBuilder addAll(JsonArrayBuilder)} method on + * {@code null} builder argument. + * + * @param result + * Test suite result. + */ + private void testAddAllNull(final TestResult result) { + System.out.println(" - addAll(JsonArrayBuilder) for null builder argument"); + JsonArrayBuilder builder = Json.createArrayBuilder(); + try { + builder.addAll((JsonArrayBuilder) null); + result.fail("addAll(null)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("addAll(null)", + "Calling method with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Test helper: Verify + * {@code default JsonArrayBuilder addAll(JsonArrayBuilder)} method on + * provided array. + * + * @param result + * Test suite result. + * @param check + * Expected value (used for operation check). + * @param values + * Values used to build JSON array builder. + */ + private void verifyAddAll(final TestResult result, final JsonArray check, + final Object[] values) { + JsonArrayBuilder builderIn = Json.createArrayBuilder(); + for (Object value : values) { + builderIn = updateOperationBuilder(builderIn, value); + } + final JsonArrayBuilder builderOut = Json.createArrayBuilder(); + builderOut.addAll(builderIn); + final JsonArray out = builderOut.build(); + if (operationFailed(check, out)) { + result.fail("addAll(JsonArrayBuilder)", "Output builder " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Test helper: Verify + * {@code default JsonArrayBuilder add(int,JsonArrayBuilder)} method on + * provided builders. + * + * @param result + * Test suite result. + * @param check + * Expected value (used for operation check). + * @param src + * Source builder (the one to be added). + * @param target + * Target builder (to which to add). + */ + private void verifyAddBuilder(final TestResult result, final JsonValue check, + final int index, final JsonArrayBuilder src, + final JsonArrayBuilder target) { + final JsonArray out = target.add(index, src).build(); + if (operationFailed(check, out)) { + result.fail("add(int,JsonArrayBuilder)", "Output builder " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Test helper: Verify + * {@code default JsonArrayBuilder add(int,JsonObjectBuilder)} method on + * provided builders. + * + * @param result + * Test suite result. + * @param check + * Expected value (used for operation check). + * @param src + * Source builder (the one to be added). + * @param target + * Target builder (to which to add). + */ + private void verifyAddBuilder(final TestResult result, final JsonValue check, + final int index, final JsonObjectBuilder src, + final JsonArrayBuilder target) { + final JsonArray out = target.add(index, src).build(); + if (operationFailed(check, out)) { + result.fail("add(int,JsonObjectBuilder)", "Output builder " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Create and initialize array builder to contain single value. Child class + * callback. + * + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder containing value. + */ + @Override + protected JsonArrayBuilder createArrayBuilder(final Object value) { + return ArrayBuilder.add(Json.createArrayBuilder(), value); + } + + /** + * Create and initialize array builder to contain single value. Child class + * callback. + * + * @param index + * Position in the array where value is added. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder containing value. + */ + @Override + protected JsonArrayBuilder createArrayBuilder(final int index, + final Object value) { + return ArrayBuilder.add(Json.createArrayBuilder(), index, value); + } + + /** + * Update array builder to contain next value. Child class callback. + * + * @param builder + * JSON array builder to update. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder with value updated. + */ + @Override + protected JsonArrayBuilder updateOperationBuilder( + final JsonArrayBuilder builder, final Object value) { + return ArrayBuilder.add(builder, value); + } + + /** + * Update array builder to contain next value. Child class callback. + * + * @param builder + * JSON array builder to update. + * @param index + * Position in the array where value is added. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder with value updated. + */ + @Override + protected JsonArrayBuilder updateOperationBuilder( + final JsonArrayBuilder builder, final int index, final Object value) { + return ArrayBuilder.add(builder, index, value); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuildRemove.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuildRemove.java new file mode 100644 index 0000000..2f5b061 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuildRemove.java
@@ -0,0 +1,206 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonarraytests; + +import jakarta.jsonp.tck.api.common.ArrayBuilder; +import jakarta.jsonp.tck.api.common.JsonIO; +import jakarta.jsonp.tck.api.common.JsonValueType; +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests: + * {@link JsonArrayBuilder} API remove() methods added in JSON-P 1.1.<br> + */ +public class ArrayBuildRemove extends ArrayCommon { + + /** + * Creates an instance of {@link JsonArrayBuilder} API remove() methods added + * in JSON-P 1.1 test. + */ + ArrayBuildRemove() { + super(); + } + + /** + * {@link JsonArrayBuilder} API remove() methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonArrayBuilder API remove() methods added in JSON-P 1.1."); + System.out.println("JsonArrayBuilder API remove() methods added in JSON-P 1.1."); + testRemove(result); + testRemoveOutOfBounds(result); + return result; + } + + /** + * Test {@code default JsonArrayBuilder remove(int, Object)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testRemove(final TestResult result) { + final Object[] values = new Object[] { OBJ_VALUE, // remove(int,JsonValue) + STR_VALUE, // remove(int,String) + INT_VALUE, // remove(int,int) + LNG_VALUE, // remove(int,long) + DBL_VALUE, // remove(int,double) + BIN_VALUE, // remove(int,BigInteger) + BDC_VALUE, // remove(int,BigDecimal) + BOOL_VALUE // remove(int,boolean) + }; + for (Object value : values) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println(" - remove(int," + typeName + ")"); + final String json = "[]"; + final JsonValue check = JsonIO.read(json); + JsonArrayBuilder builder = ArrayBuilder.add(Json.createArrayBuilder(), + value); + builder = updateOperationBuilder(builder, 0, null); + final JsonValue out = builder.build(); + if (operationFailed(check, out)) { + result.fail("remove(" + typeName + ")", "Builder output " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + } + + /** + * Test {@code default JsonArrayBuilder remove(int, Object)} method on + * {@code String} array with index being out of range + * ({@code index < 0 || index > array size}). + * + * @param result + * Test suite result. + */ + private void testRemoveOutOfBounds(final TestResult result) { + final Object[] values = new Object[] { OBJ_VALUE, // remove(int,JsonValue) + STR_VALUE, // remove(int,String) + INT_VALUE, // remove(int,int) + LNG_VALUE, // remove(int,long) + DBL_VALUE, // remove(int,double) + BIN_VALUE, // remove(int,BigInteger) + BDC_VALUE, // remove(int,BigDecimal) + BOOL_VALUE // remove(int,boolean) + }; + final int[] indexes = new int[] { -1, 2, 3 }; + for (Object value : values) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println(" - remove(int," + typeName + ")"); + final String json = "[" + JsonValueType.toStringValue(value) + "]"; + // Add value into the array for the first time to het array of size 1. + JsonArrayBuilder builder = ArrayBuilder.add(Json.createArrayBuilder(), + value); + for (int index : indexes) { + try { + // Add value on out of bounds index + builder = updateOperationBuilder(builder, index, null); + result.fail("remove(int," + typeName + ")", + "Calling method with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println(" - Expected exception for index=" + index + ": " + + e.getMessage()); + } catch (Throwable t) { + result.fail("remove(int,(" + typeName + ")null)", + "Calling method with with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException, not " + + t.getClass().getSimpleName()); + } + } + } + } + + /** + * Create and initialize array builder. Unsupported method call for remove() + * method. + * + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder containing value. + */ + @Override + protected JsonArrayBuilder createArrayBuilder(Object value) { + throw new UnsupportedOperationException( + "Method remove is not implemented."); + } + + /** + * Create and initialize array builder. Unsupported method call for remove() + * method. + * + * @param index + * Position in the array where value is added. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder containing value. + */ + @Override + protected JsonArrayBuilder createArrayBuilder(final int index, + final Object value) { + throw new UnsupportedOperationException( + "Method remove is not implemented."); + } + + /** + * Update array builder. Unsupported method call for remove() method. + * + * @param builder + * JSON array builder to update. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder with value updated. + */ + @Override + protected JsonArrayBuilder updateOperationBuilder(JsonArrayBuilder builder, + Object value) { + throw new UnsupportedOperationException( + "Method remove is not implemented."); + } + + /** + * Update array builder with value removal at specified index. Child class + * callback. + * + * @param builder + * JSON array builder to update. + * @param index + * Position in the array where value is added. + * @param value + * JSON value argument is ignored. + * @return JSON array builder with value updated. + */ + @Override + protected JsonArrayBuilder updateOperationBuilder( + final JsonArrayBuilder builder, final int index, final Object value) { + return ArrayBuilder.remove(builder, index); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuildSet.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuildSet.java new file mode 100644 index 0000000..e41ebe1 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuildSet.java
@@ -0,0 +1,494 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonarraytests; + +import jakarta.jsonp.tck.api.common.ArrayBuilder; +import jakarta.jsonp.tck.api.common.JsonIO; +import jakarta.jsonp.tck.api.common.JsonValueType; +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests: + * {@link JsonArrayBuilder} API set() methods added in JSON-P 1.1.<br> + */ +public class ArrayBuildSet extends ArrayCommon { + + /** + * Creates an instance of {@link JsonArrayBuilder} API set() methods added in + * JSON-P 1.1 test. + */ + ArrayBuildSet() { + super(); + } + + /** + * {@link JsonArrayBuilder} API set() methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonArrayBuilder API set() methods added in JSON-P 1.1."); + System.out.println("JsonArrayBuilder API set() methods added in JSON-P 1.1."); + testSet(result); + testSetOutOfBounds(result); + testSetNullBuilder(result); + testSetNull(result); + testSetNullOutOfBounds(result); + testSetArrayBuilder(result); + testSetArrayBuilderNull(result); + testSetArrayBuilderOutOfBounds(result); + testSetObjectBuilder(result); + testSetObjectBuilderNull(result); + testSetObjectBuilderOutOfBounds(result); + return result; + } + + /** + * Test {@code default JsonArrayBuilder set(int, Object)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testSet(final TestResult result) { + final Object[] values = new Object[] { OBJ_VALUE, // set(int,JsonValue) + STR_VALUE, // set(int,String) + INT_VALUE, // set(int,int) + LNG_VALUE, // set(int,long) + DBL_VALUE, // set(int,double) + BIN_VALUE, // set(int,BigInteger) + BDC_VALUE, // set(int,BigDecimal) + BOOL_VALUE // set(int,boolean) + }; + for (Object value : values) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println(" - set(int," + typeName + ")"); + final String json = "[" + JsonValueType.toStringValue(value) + "]"; + final JsonValue check = JsonIO.read(json); + final JsonArrayBuilder builder = updateOperationBuilder( + Json.createArrayBuilder().add(DEF_OBJ_VALUE), 0, value); + final JsonValue out = builder.build(); + if (operationFailed(check, out)) { + result.fail("set(" + typeName + ")", "Builder output " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + } + + /** + * Test {@code default JsonArrayBuilder set(int, Object)} method on + * {@code String} array with index being out of range + * ({@code index < 0 || index > array size}). + * + * @param result + * Test suite result. + */ + private void testSetOutOfBounds(final TestResult result) { + final Object[] values = new Object[] { OBJ_VALUE, // set(int,JsonValue) + STR_VALUE, // set(int,String) + INT_VALUE, // set(int,int) + LNG_VALUE, // set(int,long) + DBL_VALUE, // set(int,double) + BIN_VALUE, // set(int,BigInteger) + BDC_VALUE, // set(int,BigDecimal) + BOOL_VALUE // set(int,boolean) + }; + final int[] indexes = new int[] { -1, 2, 3 }; + for (Object value : values) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println(" - set(int," + typeName + ")"); + final String json = "[" + JsonValueType.toStringValue(value) + "]"; + JsonArrayBuilder builder = ArrayBuilder.add(Json.createArrayBuilder(), + DEF_OBJ_VALUE); + for (int index : indexes) { + try { + builder = updateOperationBuilder( + Json.createArrayBuilder().add(DEF_OBJ_VALUE), index, value); + } catch (IndexOutOfBoundsException e) { + System.out.println(" - Expected exception for index=" + index + ": " + + e.getMessage()); + } catch (Throwable t) { + result.fail("set(int," + typeName + ")", + "Calling method with with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException, not " + + t.getClass().getSimpleName()); + } + } + } + } + + /** + * Test {@code default JsonArrayBuilder set(int, Object)} method on + * {@code String} array with null value. + * + * @param result + * Test suite result. + */ + private void testSetNullBuilder(final TestResult result) { + final JsonValueType[] types = new JsonValueType[] { JsonValueType.JsonValue, // set(int,(JsonValue)null) + JsonValueType.String, // set(int,(String)null) + JsonValueType.BigInteger, // set(int,(BigInteger)null) + JsonValueType.BigDecimal // set(int,(BigDecimal)null) + }; + for (JsonValueType type : types) { + final String typeName = type.name(); + System.out.println(" - set(int,(" + typeName + ")null)"); + try { + ArrayBuilder.set(Json.createArrayBuilder(), 0, type); + result.fail("set(int,(" + typeName + ")null)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("set(int,(" + typeName + ")null)", + "Calling method with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code default JsonArrayBuilder setNull(int)} method on {@code String} + * array. + * + * @param result + * Test suite result. + */ + private void testSetNull(final TestResult result) { + System.out.println(" - setNull(int)"); + final Object value = null; + final String json = "[" + JsonValueType.toStringValue(null) + "]"; + final JsonValue check = JsonIO.read(json); + final JsonArrayBuilder builder = ArrayBuilder + .set(Json.createArrayBuilder().add(DEF_OBJ_VALUE), 0, value); + final JsonValue out = builder.build(); + if (operationFailed(check, out)) { + result.fail("setNull(int)", "Builder output " + valueToString(out) + + " value shall be " + valueToString(check)); + } + } + + /** + * Test {@code default JsonArrayBuilder setNull(int)} method on {@code String} + * array with index being out of range + * ({@code index < 0 || index > array size}). + * + * @param result + * Test suite result. + */ + private void testSetNullOutOfBounds(final TestResult result) { + final int[] indexes = new int[] { -1, 2, 3 }; + System.out.println(" - setNull(int)"); + final Object value = null; + JsonArrayBuilder builder = ArrayBuilder.add(Json.createArrayBuilder(), + value); + for (int index : indexes) { + try { + // Add value on out of bounds index + builder = updateOperationBuilder(builder, index, value); + result.fail("setNull(int)", "Calling method with out of bounds index=" + + index + " argument shall throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println(" - Expected exception for index=" + index + ": " + + e.getMessage()); + } catch (Throwable t) { + result.fail("setNull(int)", + "Calling method with with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code default JsonArrayBuilder set(int,JsonArrayBuilder)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testSetArrayBuilder(final TestResult result) { + System.out.println(" - set(int,JsonArrayBuilder)"); + final JsonValue check = JsonIO + .read("[[" + JsonValueType.toStringValue(STR_VALUE_1) + "," + + JsonValueType.toStringValue(STR_VALUE_2) + "," + + JsonValueType.toStringValue(STR_VALUE_3) + "," + + JsonValueType.toStringValue(STR_VALUE_4) + "]]"); + final JsonArrayBuilder in = Json.createArrayBuilder().add(STR_VALUE_5); + final JsonArrayBuilder arg = Json.createArrayBuilder().add(STR_VALUE_1) + .add(STR_VALUE_2).add(STR_VALUE_3).add(STR_VALUE_4); + verifySetBuilder(result, check, 0, arg, in); + } + + /** + * Test {@code default JsonArrayBuilder set(int,(JsonArrayBuilder)null)} + * method on {@code String} array. + * + * @param result + * Test suite result. + */ + private void testSetArrayBuilderNull(final TestResult result) { + System.out.println(" - set(int,(JsonArrayBuilder)null)"); + final JsonArrayBuilder in = Json.createArrayBuilder().add(DEF_VALUE); + final JsonArrayBuilder arg = null; + try { + in.set(0, arg); + result.fail("set(int,(JsonArrayBuilder)null)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("set(int,(JsonArrayBuilder)null)", + "Calling method with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Test {@code default JsonArrayBuilder set(int,JsonArrayBuilder)} method on + * {@code String} array with index being out of range + * ({@code index < 0 || index > array size}). + * + * @param result + * Test suite result. + */ + private void testSetArrayBuilderOutOfBounds(final TestResult result) { + System.out.println(" - set(int,JsonArrayBuilder)"); + final int[] indexes = new int[] { -1, 5, 6 }; + final JsonArrayBuilder in = Json.createArrayBuilder().add(STR_VALUE_1) + .add(STR_VALUE_2).add(STR_VALUE_3).add(STR_VALUE_4); + final JsonArrayBuilder arg = Json.createArrayBuilder().add(STR_VALUE_5); + for (int index : indexes) { + try { + // Add value on out of bounds index + in.set(index, arg); + result.fail("set(int,JsonArrayBuilder)", + "Calling method with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println(" - Expected exception for index=" + index + ": " + + e.getMessage()); + } catch (Throwable t) { + result.fail("set(int,JsonArrayBuilder)", + "Calling method with with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code default JsonArrayBuilder set(int,JsonObjectBuilder)} method on + * {@code String} array. + * + * @param result + * Test suite result. + */ + private void testSetObjectBuilder(final TestResult result) { + System.out.println(" - set(int,JsonObjectBuilder)"); + final JsonValue check = JsonIO + .read("[{" + JsonValueType.toStringValue(STR_NAME) + ":" + + JsonValueType.toStringValue(STR_VALUE) + "}]"); + final JsonArrayBuilder in = Json.createArrayBuilder().add(STR_VALUE_1); + final JsonObjectBuilder arg = Json.createObjectBuilder().add(STR_NAME, + STR_VALUE); + verifySetBuilder(result, check, 0, arg, in); + } + + /** + * Test {@code default JsonArrayBuilder set(int,(JsonObjectBuilder)null)} + * method on {@code String} array. + * + * @param result + * Test suite result. + */ + private void testSetObjectBuilderNull(final TestResult result) { + System.out.println(" - set(int,(JsonObjectBuilder)null)"); + final JsonArrayBuilder in = Json.createArrayBuilder().add(DEF_VALUE); + final JsonObjectBuilder arg = null; + try { + in.set(0, arg); + result.fail("set(int,(JsonObjectBuilder)null)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("set(int,(JsonObjectBuilder)null)", + "Calling method with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Test {@code default JsonArrayBuilder set(int,JsonObjectBuilder)} method on + * {@code String} array with index being out of range + * ({@code index < 0 || index > array size}). + * + * @param result + * Test suite result. + */ + private void testSetObjectBuilderOutOfBounds(final TestResult result) { + System.out.println(" - set(int,JsonObjectBuilder)"); + final int[] indexes = new int[] { -1, 5, 6 }; + final JsonArrayBuilder in = Json.createArrayBuilder().add(STR_VALUE_1) + .add(STR_VALUE_2).add(STR_VALUE_3).add(STR_VALUE_4); + final JsonObjectBuilder arg = Json.createObjectBuilder().add(STR_NAME, + STR_VALUE); + for (int index : indexes) { + try { + // Add value on out of bounds index + in.set(index, arg); + result.fail("set(int,JsonObjectBuilder)", + "Calling method with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println(" - Expected exception for index=" + index + ": " + + e.getMessage()); + } catch (Throwable t) { + result.fail("set(int,JsonObjectBuilder)", + "Calling method with with out of bounds index=" + index + + " argument shall throw IndexOutOfBoundsException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test helper: Verify + * {@code default JsonArrayBuilder set(int,JsonArrayBuilder)} method on + * provided builders. + * + * @param result + * Test suite result. + * @param check + * Expected value (used for operation check). + * @param src + * Source builder (the one to be added). + * @param target + * Target builder (to which to add). + */ + private void verifySetBuilder(final TestResult result, final JsonValue check, + final int index, final JsonArrayBuilder src, + final JsonArrayBuilder target) { + final JsonArray out = target.set(index, src).build(); + if (operationFailed(check, out)) { + result.fail("set(int,JsonArrayBuilder)", "Output builder " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Test helper: Verify + * {@code default JsonArrayBuilder set(int,JsonObjectBuilder)} method on + * provided builders. + * + * @param result + * Test suite result. + * @param check + * Expected value (used for operation check). + * @param src + * Source builder (the one to be added). + * @param target + * Target builder (to which to add). + */ + private void verifySetBuilder(final TestResult result, final JsonValue check, + final int index, final JsonObjectBuilder src, + final JsonArrayBuilder target) { + final JsonArray out = target.set(index, src).build(); + if (operationFailed(check, out)) { + result.fail("set(int,JsonObjectBuilder)", "Output builder " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Create and initialize array builder to contain single value. Unsupported + * method call for set() method. + * + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder containing value. + */ + @Override + protected JsonArrayBuilder createArrayBuilder(Object value) { + throw new UnsupportedOperationException("Method set is not implemented."); + } + + /** + * Create and initialize array builder to contain single value. Child class + * callback. + * + * @param index + * Position in the array where value is added. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder containing value. + */ + @Override + protected JsonArrayBuilder createArrayBuilder(final int index, + final Object value) { + return ArrayBuilder.set(Json.createArrayBuilder(), index, value); + } + + /** + * Update array builder to contain next value. Unsupported method call for + * set() method. + * + * @param builder + * JSON array builder to update. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder with value updated. + */ + @Override + protected JsonArrayBuilder updateOperationBuilder(JsonArrayBuilder builder, + Object value) { + throw new UnsupportedOperationException("Method set is not implemented."); + } + + /** + * Update array builder to contain next value. Child class callback. + * + * @param builder + * JSON array builder to update. + * @param index + * Position in the array where value is added. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder with value updated. + */ + @Override + protected JsonArrayBuilder updateOperationBuilder( + final JsonArrayBuilder builder, final int index, final Object value) { + return ArrayBuilder.set(builder, index, value); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuilders.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuilders.java new file mode 100644 index 0000000..9a71d27 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayBuilders.java
@@ -0,0 +1,171 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonarraytests; + +import jakarta.jsonp.tck.api.common.TestResult; +import java.util.ArrayList; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonString; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; +import java.util.Iterator; +import java.util.List; +import jakarta.json.JsonNumber; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests: + * {@link JsonArrayBuilder} API factory methods added in JSON-P 1.1.<br> + */ +public class ArrayBuilders { + + /** + * Creates an instance of {@link JsonArrayBuilder} API factory methods added + * in JSON-P 1.1 test. + */ + ArrayBuilders() { + super(); + } + + /** + * Test {@link JsonArrayBuilder} factory method added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonArrayBuilder API factory methods added in JSON-P 1.1."); + System.out.println("JsonArrayBuilder API factory methods added in JSON-P 1.1."); + testCreateFromCollection(result); + testCreateFromJsonArray(result); + testGetStringValuesAs(result); + testGetIntValuesAs(result); + return result; + } + + /** + * Test {@link Json#createArrayBuilder(Collection<Object>)} method. + * + * @param result + * Test suite result. + */ + private void testCreateFromCollection(final TestResult result) { + System.out.println(" - Json#createArrayBuilder(Collection<Object>)"); + final JsonArray check = createSimpleStringArray5(); + final ArrayList<Object> values = new ArrayList<>(check.size()); + for (final JsonValue value : check) { + values.add(((JsonString) value).getString()); + } + final JsonArrayBuilder builder = Json.createArrayBuilder(values); + final JsonArray out = builder.build(); + if (operationFailed(check, out)) { + result.fail("createArrayBuilder(Collection<Object>)", "Builder output " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Test {@link Json#createArrayBuilder(JsonArray)} method. + * + * @param result + * Test suite result. + */ + private void testCreateFromJsonArray(final TestResult result) { + System.out.println(" - Json#createArrayBuilder(JsonArray)"); + final JsonArray check = createSimpleStringArray5(); + final JsonArrayBuilder builder = Json.createArrayBuilder(check); + final JsonArray out = builder.build(); + if (operationFailed(check, out)) { + result.fail("createArrayBuilder(JsonArray)", "Builder output " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Test {@code default JsonArray#getValuesAs(Function<K,T>)} method on + * {@code String} values. + * + * @param result + * Test suite result. + */ + private void testGetStringValuesAs(final TestResult result) { + System.out.println(" - getValuesAs(Function<K,T> on String array"); + final JsonArray in = createStringArray2(); + final List<String> out = in.getValuesAs(JsonString::getString); + boolean failed = in.size() != out.size(); + if (!failed) { + final Iterator<JsonValue> inIt = in.iterator(); + final Iterator<String> outIt = out.iterator(); + while (!failed && inIt.hasNext()) { + final JsonValue inVal = inIt.next(); + final String outVal = outIt.next(); + failed = !((JsonString) inVal).getString().equals(outVal); + } + } + if (failed) { + result.fail("getValuesAs(Function<K,T>)", "Returned Array " + + out.toString() + " content shall match " + valueToString(in)); + } + } + + /** + * Test {@code default JsonArray#getValuesAs(Function<K,T>)} method on + * {@code int} values. + * + * @param result + * Test suite result. + */ + private void testGetIntValuesAs(final TestResult result) { + System.out.println(" - getValuesAs(Function<K,T> on int array"); + final JsonArray in = createIntArray2(); + final List<Integer> out = in.getValuesAs(JsonNumber::intValue); + boolean failed = in.size() != out.size(); + if (!failed) { + final Iterator<JsonValue> inIt = in.iterator(); + final Iterator<Integer> outIt = out.iterator(); + while (!failed && inIt.hasNext()) { + final JsonValue inVal = inIt.next(); + final Integer outVal = outIt.next(); + failed = ((JsonNumber) inVal).intValue() != outVal; + } + } + if (failed) { + result.fail("getValuesAs(Function<K,T>)", "Returned Array " + + out.toString() + " content shall match " + valueToString(in)); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayCommon.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayCommon.java new file mode 100644 index 0000000..1560b36 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ArrayCommon.java
@@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonarraytests; + +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests for {@link JsonArray} + * and {@link JsonArrayBuilder}. + */ +public abstract class ArrayCommon { + + /** + * Create and initialize array builder to contain single value. Child class + * callback. + * + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder containing value. + */ + protected abstract JsonArrayBuilder createArrayBuilder(final Object value); + + /** + * Create and initialize array builder to contain single value. Child class + * callback. + * + * @param index + * Position in the array where value is added. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder containing value. + */ + protected abstract JsonArrayBuilder createArrayBuilder(final int index, + final Object value); + + /** + * Update array builder to contain next value. Child class callback. + * + * @param builder + * JSON array builder to update. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder with value updated. + */ + protected abstract JsonArrayBuilder updateOperationBuilder( + final JsonArrayBuilder builder, final Object value); + + /** + * Update array builder to contain next value. Child class callback. + * + * @param builder + * JSON array builder to update. + * @param index + * Position in the array where value is added. + * @param value + * JSON value stored in the builder. Value of {@code null} is stored + * as JSON {@code null} keyword. + * @return JSON array builder with value updated. + */ + protected abstract JsonArrayBuilder updateOperationBuilder( + final JsonArrayBuilder builder, final int index, final Object value); + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ClientTests.java new file mode 100644 index 0000000..0fa1978 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonarraytests/ClientTests.java
@@ -0,0 +1,1428 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonarraytests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.json.*; + +//$Id$ + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonArrayTest1 + * + * @assertion_ids: JSONP:JAVADOC:6; JSONP:JAVADOC:8; JSONP:JAVADOC:10; + * JSONP:JAVADOC:12; JSONP:JAVADOC:14; JSONP:JAVADOC:16; JSONP:JAVADOC:18; + * JSONP:JAVADOC:25; JSONP:JAVADOC:21; JSONP:JAVADOC:400; JSONP:JAVADOC:401; + * JSONP:JAVADOC:402; JSONP:JAVADOC:403; JSONP:JAVADOC:404; JSONP:JAVADOC:406; + * JSONP:JAVADOC:408; JSONP:JAVADOC:409; + * + * @test_Strategy: Tests JsonArray/JsonArrayBuilder API's. Build a JsonArray + * using the JsonArrayBuilder API's then verify that the list of JsonArray + * values matches the expected list of JsonArray values. + */ + @Test + public void jsonArrayTest1() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject object = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create sample JsonArray for testing"); + JsonArray array = JSONP_Util.createSampleJsonArray(); + + System.out.println("Create the expected list of JsonArray values"); + List<JsonValue> expList = new ArrayList<>(); + expList.add(JsonValue.FALSE); + expList.add(JsonValue.TRUE); + expList.add(JsonValue.NULL); + expList.add(JSONP_Util.createJsonNumber(Double.MIN_VALUE)); + expList.add(JSONP_Util.createJsonNumber(Double.MAX_VALUE)); + expList.add(JSONP_Util.createJsonNumber(Integer.MIN_VALUE)); + expList.add(JSONP_Util.createJsonNumber(Integer.MAX_VALUE)); + expList.add(JSONP_Util.createJsonNumber(Long.MIN_VALUE)); + expList.add(JSONP_Util.createJsonNumber(Long.MAX_VALUE)); + expList.add( + JSONP_Util.createJsonNumber(BigDecimal.valueOf(123456789.123456789))); + expList.add(JSONP_Util.createJsonNumber(new BigInteger("123456789"))); + expList.add(JSONP_Util.createJsonString("string1")); + expList.add(object); + expList.add(array); + JSONP_Util.dumpList(expList, "Expected List"); + + System.out.println("Create JsonArray using all JsonArrayBuilder API's"); + JsonArray myJsonArray = Json.createArrayBuilder() // Indices + .add(JsonValue.FALSE) // 0 + .add(JsonValue.TRUE) // 1 + .add(JsonValue.NULL) // 2 + .add(Double.MIN_VALUE) // 3 + .add(Double.MAX_VALUE) // 4 + .add(Integer.MIN_VALUE) // 5 + .add(Integer.MAX_VALUE) // 6 + .add(Long.MIN_VALUE) // 7 + .add(Long.MAX_VALUE) // 8 + .add(BigDecimal.valueOf(123456789.123456789)) // 9 + .add(new BigInteger("123456789")) // 10 + .add("string1") // 11 + .add(object) // 12 + .add(array) // 13 + .build(); + + List<JsonValue> actualList = myJsonArray; + JSONP_Util.dumpList(actualList, "Actual List"); + System.out.println( + "Compare actual list of JsonArray values with expected list of JsonArray values"); + pass = JSONP_Util.assertEqualsList(expList, actualList); + } catch (Exception e) { + throw new Fault("jsonArrayTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonArrayTest1 Failed"); + } + + /* + * @testName: jsonArrayTest2 + * + * @assertion_ids: JSONP:JAVADOC:6; JSONP:JAVADOC:8; JSONP:JAVADOC:10; + * JSONP:JAVADOC:12; JSONP:JAVADOC:14; JSONP:JAVADOC:16; JSONP:JAVADOC:18; + * JSONP:JAVADOC:105; JSONP:JAVADOC:106; JSONP:JAVADOC:108; JSONP:JAVADOC:96; + * JSONP:JAVADOC:97; JSONP:JAVADOC:21; JSONP:JAVADOC:25; JSONP:JAVADOC:184; + * JSONP:JAVADOC:400; JSONP:JAVADOC:401; JSONP:JAVADOC:402; JSONP:JAVADOC:403; + * JSONP:JAVADOC:404; JSONP:JAVADOC:406; JSONP:JAVADOC:408; JSONP:JAVADOC:409; + * + * + * @test_Strategy: Tests JsonArray/JsonArrayBuilder API's. Build a JsonArray + * using the JsonArrayBuilder API's. Write the JsonArray to a JsonWriter and + * read it back using a JsonReader. Verify that JsonArray written to the + * JsonWriter and then read back using the JsonReader are equal. + */ + @Test + public void jsonArrayTest2() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject object = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create sample JsonArray for testing"); + JsonArray array = JSONP_Util.createSampleJsonArray(); + + System.out.println( + "Create JsonArray 'myJsonArray1' using all JsonArrayBuilder API's"); + JsonArray myJsonArray1 = Json.createArrayBuilder() // Indices + .add(JsonValue.FALSE) // 0 + .add(JsonValue.TRUE) // 1 + .add(JsonValue.NULL) // 2 + .add(Double.MIN_VALUE) // 3 + .add(Double.MAX_VALUE) // 4 + .add(Integer.MIN_VALUE) // 5 + .add(Integer.MAX_VALUE) // 6 + .add(Long.MIN_VALUE) // 7 + .add(Long.MAX_VALUE) // 8 + .add(BigDecimal.valueOf(123456789.123456789)) // 9 + .add(new BigInteger("123456789")) // 10 + .add("string1") // 11 + .add(object) // 12 + .add(array) // 13 + .build(); + + System.out.println("Write the JsonArray 'myJsonArray1' out to a JsonWriter"); + StringWriter sw = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sw)) { + writer.writeArray(myJsonArray1); + System.out.println("Close JsonWriter"); + } + System.out.println("Save contents of the JsonWriter as a String"); + String contents = sw.toString(); + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + contents); + System.out.println("Read the JsonArray back into 'myJsonArray2' using a JsonReader"); + JsonArray myJsonArray2; + try (JsonReader reader = Json.createReader(new StringReader(contents))) { + myJsonArray2 = reader.readArray(); + } + System.out.println("Dump contents of JsonArray read from String Contents"); + JSONP_Util.dumpJsonValue(myJsonArray2); + + System.out.println("Compare myJsonArray1 and myJsonArray2 for equality"); + pass = JSONP_Util.assertEqualsJsonArrays(myJsonArray1, myJsonArray2); + } catch (Exception e) { + throw new Fault("jsonArrayTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonArrayTest2 Failed"); + } + + /* + * @testName: jsonArrayTest3 + * + * @assertion_ids: JSONP:JAVADOC:6; JSONP:JAVADOC:8; JSONP:JAVADOC:10; + * JSONP:JAVADOC:430; JSONP:JAVADOC:12; JSONP:JAVADOC:14; JSONP:JAVADOC:16; + * JSONP:JAVADOC:18; JSONP:JAVADOC:40; JSONP:JAVADOC:41; JSONP:JAVADOC:42; + * JSONP:JAVADOC:44; JSONP:JAVADOC:45; JSONP:JAVADOC:46; JSONP:JAVADOC:48; + * JSONP:JAVADOC:49; JSONP:JAVADOC:51; JSONP:JAVADOC:21; JSONP:JAVADOC:25; + * JSONP:JAVADOC:101; JSONP:JAVADOC:102; JSONP:JAVADOC:262; JSONP:JAVADOC:263; + * JSONP:JAVADOC:400; JSONP:JAVADOC:401; JSONP:JAVADOC:402; JSONP:JAVADOC:403; + * JSONP:JAVADOC:404; JSONP:JAVADOC:406; JSONP:JAVADOC:408; JSONP:JAVADOC:409; + * JSONP:JAVADOC:433; JSONP:JAVADOC:434; JSONP:JAVADOC:435; JSONP:JAVADOC:490; + * JSONP:JAVADOC:493; JSONP:JAVADOC:496; JSONP:JAVADOC:499; JSONP:JAVADOC:506; + * + * @test_Strategy: Tests JsonArray/JsonArrayBuilder API's. Build a JsonArray + * using the JsonArrayBuilder API's. Verify contents of JsonArray using + * JsonArray().getJsonNumber(int), JsonArray().getJsonString(int), + * JsonArray().getJsonArray(int), JsonArray().getJsonObject(). + * + * This also covers testing the following additional API's: + * + * JsonString.getString(), JsonNumber.bigDecimalValue(), + * JsonNumber.bigIntegerValue(), JsonNumber.doubleValue(), + * JsonNumber.intValue(), JsonNumber.longValue(), JsonNumber.isIntegral(), + * JsonNumber.longValueExact(), JsonNumber.intValueExact(), + * JsonNumber.bigIntegerValueExact(), JsonArray.getInt(int), + * JsonArray.getString(int), JsonArrau.getBoolean(int), + * JsonArray.getBoolean(int, boolean), JsonArray.getInt(int, int), + * JsonArray.getString(int, String) + */ + @SuppressWarnings("SuspiciousIndentAfterControlStatement") + @Test + public void jsonArrayTest3() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject object = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create sample JsonArray for testing"); + JsonArray array = JSONP_Util.createSampleJsonArray(); + + int expInt[] = { -1, 1, 1, -1000, 1000, 1000, -2000, 2000, 2000, + Integer.MAX_VALUE, Integer.MIN_VALUE }; + + long expLong[] = { Long.MAX_VALUE, Long.MIN_VALUE }; + + double expDouble[] = { Double.MAX_VALUE, Double.MIN_VALUE }; + + System.out.println("Create myArray Jsonarray of 23 elements"); + JsonArray myArray = Json.createArrayBuilder() // Indices + .add(-1).add(+1).add(1) // 0,1,2 + .add(-1e3).add(+1e3).add(1e3) // 3,4,5 + .add(-2E3).add(+2E3).add(2E3) // 6,7,8 + .add(Integer.MAX_VALUE) // 9 + .add(Integer.MIN_VALUE) // 10 + .add(Long.MAX_VALUE) // 11 + .add(Long.MIN_VALUE) // 12 + .add(Double.MAX_VALUE) // 13 + .add(Double.MIN_VALUE) // 14 + .add(BigDecimal.valueOf(123456789.123456789)) // 15 + .add(new BigInteger("123456789")) // 16 + .add(JsonValue.TRUE) // 17 + .add(JsonValue.FALSE) // 18 + .add(JsonValue.NULL) // 19 + .add(JSONP_Data.asciiCharacters) // 20 + .add(object) // 21 + .add(array) // 22 + .build(); + + System.out.println("Array size=" + myArray.size()); + + // Following array is used to test for Ints that could be one of following + // types: + boolean expectedIntTypes[] = { JSONP_Util.INTEGRAL, + JSONP_Util.NON_INTEGRAL }; + // Verify JsonValueType=NUMBER and integer value equals expectedIntValue + for (int i = 0; i < 11; i++) { + System.out.println("Checking getValue(" + i + ") for correctness"); + System.out.println("Retrieve and verify (JsonValueType=NUMBER)"); + if (!JSONP_Util.assertEqualsJsonValueType(JsonValue.ValueType.NUMBER, + myArray.getJsonNumber(i).getValueType())) + pass = false; + System.out.println("Retrieve and (expect JsonNumber NumberType be one of " + + JSONP_Util.toStringJsonNumberTypes(expectedIntTypes) + ")"); + if (!JSONP_Util.assertEqualsJsonNumberTypes(expectedIntTypes, + myArray.getJsonNumber(i).isIntegral())) + pass = false; + System.out.println("Retrieve and verify integer value via JsonNumber.intValue()"); + if (!JSONP_Util.assertEquals(expInt[i], + myArray.getJsonNumber(i).intValue())) + pass = false; + System.out.println("Retrieve and verify integer value via JsonArray.getInt"); + if (!JSONP_Util.assertEquals(expInt[i], myArray.getInt(i))) + pass = false; + System.out.println( + "Retrieve and verify integer value via JsonNumber.intValueExact()"); + if (!JSONP_Util.assertEquals(expInt[i], + myArray.getJsonNumber(i).intValueExact())) + pass = false; + } + + // Verify JsonValueType=NUMBER and long value equals expectedLongValue + for (int i = 11, j = 0; i < 13; i++, j++) { + System.out.println("Checking getValue(" + i + ") for correctness"); + System.out.println("Retrieve and verify (JsonValueType=NUMBER)"); + if (!JSONP_Util.assertEqualsJsonValueType(JsonValue.ValueType.NUMBER, + myArray.getJsonNumber(i).getValueType())) + pass = false; + System.out.println("Retrieve and (expect JsonNumber NumberType be INTEGRAL)"); + if (!JSONP_Util.assertEqualsJsonNumberType(JSONP_Util.INTEGRAL, + myArray.getJsonNumber(i).isIntegral())) + pass = false; + System.out.println("Retrieve and verify long value via JsonNumber.longValue()"); + if (!JSONP_Util.assertEquals(expLong[j], + myArray.getJsonNumber(i).longValue())) + pass = false; + System.out.println( + "Retrieve and verify long value via JsonNumber.longValueExact()"); + if (!JSONP_Util.assertEquals(expLong[j], + myArray.getJsonNumber(i).longValueExact())) + pass = false; + } + + // Following array is used to test for Doubles that could be one of + // following types: + boolean expectedDoubleTypes[] = { JSONP_Util.INTEGRAL, + JSONP_Util.NON_INTEGRAL }; + + // Verify JsonValueType=NUMBER and double value equals expectedDoubleValue + for (int i = 13, j = 0; i < 15; i++, j++) { + System.out.println("Checking getValue(" + i + ") for correctness"); + System.out.println("Retrieve and verify (JsonValueType=NUMBER)"); + if (!JSONP_Util.assertEqualsJsonValueType(JsonValue.ValueType.NUMBER, + myArray.getJsonNumber(i).getValueType())) + pass = false; + System.out.println("Retrieve and (expect JsonNumber NumberType be one of " + + JSONP_Util.toStringJsonNumberTypes(expectedDoubleTypes) + ")"); + if (!JSONP_Util.assertEqualsJsonNumberTypes(expectedDoubleTypes, + myArray.getJsonNumber(i).isIntegral())) + pass = false; + System.out.println("Retrieve and verify double value via JsonNumber.doubleValue()"); + if (!JSONP_Util.assertEquals(expDouble[j], + myArray.getJsonNumber(i).doubleValue())) + pass = false; + } + + // Verify JsonValueType=NUMBER and BigDecimalValue equals + // expectedBigDecimal + System.out.println("Checking getValue(15) for correctness"); + System.out.println("Retrieve and verify (JsonValueType=NUMBER)"); + if (!JSONP_Util.assertEqualsJsonValueType(JsonValue.ValueType.NUMBER, + myArray.getJsonNumber(15).getValueType())) + pass = false; + System.out.println("Retrieve and (expect JsonNumber NumberType be one of " + + JSONP_Util.toStringJsonNumberTypes(expectedDoubleTypes) + ")"); + if (!JSONP_Util.assertEqualsJsonNumberTypes(expectedDoubleTypes, + myArray.getJsonNumber(15).isIntegral())) + pass = false; + System.out.println( + "Retrieve and verify BigDecimal value via JsonNumber.bigDecimalValue()"); + if (!JSONP_Util.assertEquals(BigDecimal.valueOf(123456789.123456789), + myArray.getJsonNumber(15).bigDecimalValue())) + pass = false; + + // Verify JsonValueType=NUMBER and BigIntegerValue equals + // expectedBigInteger + System.out.println("Checking getValue(16) for correctness"); + System.out.println("Retrieve and verify (JsonValueType=NUMBER)"); + if (!JSONP_Util.assertEqualsJsonValueType(JsonValue.ValueType.NUMBER, + myArray.getJsonNumber(16).getValueType())) + pass = false; + System.out.println("Retrieve and (expect JsonNumber NumberType be INTEGRAL)"); + if (!JSONP_Util.assertEqualsJsonNumberType(JSONP_Util.INTEGRAL, + myArray.getJsonNumber(16).isIntegral())) + pass = false; + System.out.println( + "Retrieve and verify BigInteger value via JsonNumber.bigIntegerValue()"); + if (!JSONP_Util.assertEquals(new BigInteger("123456789"), + myArray.getJsonNumber(16).bigIntegerValue())) + pass = false; + System.out.println( + "Retrieve and verify BigInteger value via JsonNumber.bigIntegerValueExact()"); + if (!JSONP_Util.assertEquals(new BigInteger("123456789"), + myArray.getJsonNumber(16).bigIntegerValueExact())) + pass = false; + + // Verify getBoolean(int)=true + System.out.println("Retrieve and verify true value via JsonArray.getBoolean(int)"); + if (!JSONP_Util.assertEquals(true, myArray.getBoolean(17))) + pass = false; + + // Verify getBoolean(int)=false + System.out.println("Retrieve and verify false value via JsonArray.getBoolean(int)"); + if (!JSONP_Util.assertEquals(false, myArray.getBoolean(18))) + pass = false; + + // Verify isNull(int)=true + System.out.println("Retrieve and verify null value via JsonArray.isNull(int)"); + if (!JSONP_Util.assertEquals(true, myArray.isNull(19))) + pass = false; + + // Verify isNull(int)=false + System.out.println("Retrieve and verify non-null value via JsonArray.isNull(int)"); + if (!JSONP_Util.assertEquals(false, myArray.isNull(20))) + pass = false; + + // Verify JsonValueType=STRING and getJsonString()=expectedString + System.out.println("Checking getValue(20) for correctness"); + System.out.println("Retrieve and (expect JsonValueType=STRING)"); + if (!JSONP_Util.assertEqualsJsonValueType(JsonValue.ValueType.STRING, + myArray.getJsonString(20).getValueType())) + pass = false; + System.out.println("Retrieve and verify string value via JsonString.getString()"); + if (!JSONP_Util.assertEquals(JSONP_Data.asciiCharacters, + myArray.getJsonString(20).getString())) + pass = false; + System.out.println("Retrieve and verify string value via JsonArray.getString()"); + if (!JSONP_Util.assertEquals(JSONP_Data.asciiCharacters, + myArray.getString(20))) + pass = false; + + // Verify JsonValueType=OBJECT and getJsonObject()=expectedObject + System.out.println("Checking getJsonObject(21) for correctness"); + System.out.println("Retrieve and (expect JsonValueType=OBJECT)"); + if (!JSONP_Util.assertEqualsJsonValueType(JsonValue.ValueType.OBJECT, + myArray.getJsonObject(21).getValueType())) + pass = false; + System.out.println( + "Retrieve and verify object value via JsonArray.getJsonObject(int)"); + if (!JSONP_Util.assertEqualsJsonObjects(object, + myArray.getJsonObject(21))) + pass = false; + + // Verify JsonValueType=ARRAY and getJsonArray()=expectedArray + System.out.println("Checking getJsonArray(22) for correctness"); + System.out.println("Retrieve and (expect JsonValueType=ARRAY)"); + if (!JSONP_Util.assertEqualsJsonValueType(JsonValue.ValueType.ARRAY, + myArray.getJsonArray(22).getValueType())) + pass = false; + System.out.println("Retrieve and verify array value via JsonArray.getJsonArray(int)"); + if (!JSONP_Util.assertEqualsJsonArrays(array, myArray.getJsonArray(22))) + pass = false; + + // Verify calls to JsonArray.getBoolean(int) + if (!JSONP_Util.assertEquals(true, myArray.getBoolean(17))) + pass = false; + if (!JSONP_Util.assertEquals(false, myArray.getBoolean(18))) + pass = false; + + // Verify calls to JsonArray.getBoolean(int, boolean) + System.out.println( + "Testing JsonArray.getBoolean(int, boolean) with/without default value setting."); + if (!JSONP_Util.assertEquals(true, myArray.getBoolean(17, false))) + pass = false; + if (!JSONP_Util.assertEquals(false, myArray.getBoolean(0, false))) + pass = false; + if (!JSONP_Util.assertEquals(false, myArray.getBoolean(19, false))) + pass = false; + if (!JSONP_Util.assertEquals(false, myArray.getBoolean(20, false))) + pass = false; + if (!JSONP_Util.assertEquals(false, myArray.getBoolean(21, false))) + pass = false; + if (!JSONP_Util.assertEquals(false, myArray.getBoolean(22, false))) + pass = false; + + // Verify calls to JsonArray.getInt(int, int) + System.out.println( + "Testing JsonArray.getInt(int, int) with/without default value setting."); + if (!JSONP_Util.assertEquals(-1, myArray.getInt(0, 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myArray.getInt(17, 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myArray.getInt(19, 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myArray.getInt(20, 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myArray.getInt(21, 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myArray.getInt(22, 10))) + pass = false; + + // Verify calls to JsonArray.getString(int, String) + System.out.println( + "Testing JsonArray.getString(int, String) with/without default value setting."); + if (!JSONP_Util.assertEquals(JSONP_Data.asciiCharacters, + myArray.getString(20, "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myArray.getString(17, "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myArray.getString(19, "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myArray.getString(2, "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myArray.getString(21, "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myArray.getString(22, "foo"))) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonArrayTest3 Failed: ", e); + } + if (!pass) + throw new Fault("jsonArrayTest3 Failed"); + } + + /* + * @testName: jsonArrayTest4 + * + * @assertion_ids: JSONP:JAVADOC:6; JSONP:JAVADOC:8; JSONP:JAVADOC:14; + * JSONP:JAVADOC:16; JSONP:JAVADOC:18; JSONP:JAVADOC:21; JSONP:JAVADOC:25; + * JSONP:JAVADOC:106; JSONP:JAVADOC:400; JSONP:JAVADOC:401; JSONP:JAVADOC:402; + * JSONP:JAVADOC:403; JSONP:JAVADOC:404; JSONP:JAVADOC:406; JSONP:JAVADOC:409; + * + * @test_Strategy: Build a JsonArray and than write the JsonArray. Compare the + * Json text from the writer contents with the expected Json text output + * expected based on the JsonArray. + */ + @Test + public void jsonArrayTest4() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonArray for testing"); + JsonArray myJsonArray1 = JSONP_Util.createSampleJsonArray(); + System.out.println("Write the JsonArray 'myJsonArray1' out to a JsonWriter"); + StringWriter sw = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sw)) { + writer.writeArray(myJsonArray1); + System.out.println("Close JsonWriter"); + } + System.out.println("Save contents of the JsonWriter as a String"); + String contents = sw.toString(); + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + contents); + System.out.println("Remove whitespace from contents."); + String actJsonText = JSONP_Util.removeWhitespace(contents); + System.out.println( + "Compare expected JsonArray text with actual JsonArray text for equality"); + pass = JSONP_Util.assertEqualsJsonText( + JSONP_Util.EXPECTED_SAMPLEJSONARRAY_TEXT, actJsonText); + } catch (Exception e) { + throw new Fault("jsonArrayTest4 Failed: ", e); + } + if (!pass) + throw new Fault("jsonArrayTest4 Failed"); + } + + /* + * @testName: jsonArrayGetValuesAsTest + * + * @assertion_ids: JSONP:JAVADOC:403; JSONP:JAVADOC:481; JSONP:JAVADOC:8; + * JSONP:JAVADOC:14; + * + * @test_Strategy: Build a Json array of values of the same type. Get the + * values as a list for that type. Compare results in list to what is expected + * for equality. + * + * APIs called: JsonArray array = Json.createArrayBuilder().add(...).build() + * List<T> JsonArray.getValuesAs(Class) + */ + @SuppressWarnings("SuspiciousIndentAfterControlStatement") + @Test + public void jsonArrayGetValuesAsTest() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonArray of JsonNumber types for testing"); + JsonArray jsonArr = Json.createArrayBuilder().add(100).add(500).build(); + + System.out.println("Create the expected list of JsonArray values"); + List<JsonValue> expList = new ArrayList<>(); + expList.add(JSONP_Util.createJsonNumber(100)); + expList.add(JSONP_Util.createJsonNumber(500)); + JSONP_Util.dumpList(expList, "Expected List"); + + System.out.println("Create the JsonNumber list of JsonArray values"); + List<JsonNumber> numList = jsonArr.getValuesAs(JsonNumber.class); + + System.out.println("Create the actual list of JsonArray values"); + List<JsonValue> actList = new ArrayList<>(); + for (JsonNumber num : numList) + actList.add(num); + + System.out.println("Compare actual list with expected list for equality"); + pass = JSONP_Util.assertEqualsList(expList, actList); + + System.out.println("Create sample JsonArray of JsonString types for testing"); + jsonArr = Json.createArrayBuilder().add("hello").add("world").build(); + + System.out.println("Create the list of JsonString values"); + List<JsonString> strList = jsonArr.getValuesAs(JsonString.class); + + System.out.println("Comparing JsonString list elements to expected values."); + if (!JSONP_Util.assertEquals(jsonArr.getString(0), + strList.get(0).getString())) + pass = false; + + if (!JSONP_Util.assertEquals(jsonArr.getString(1), + strList.get(1).getString())) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonArrayGetValuesAsTest Failed: ", e); + } + if (!pass) + throw new Fault("jsonArrayGetValuesAsTest Failed"); + } + + /* + * @testName: jsonArrayExceptionTests + * + * @assertion_ids: JSONP:JAVADOC:43; JSONP:JAVADOC:47; JSONP:JAVADOC:50; + * JSONP:JAVADOC:20; JSONP:JAVADOC:377; JSONP:JAVADOC:432; JSONP:JAVADOC:379; + * JSONP:JAVADOC:378; JSONP:JAVADOC:380; JSONP:JAVADOC:431; JSONP:JAVADOC:400; + * JSONP:JAVADOC:401; JSONP:JAVADOC:402; JSONP:JAVADOC:403; JSONP:JAVADOC:404; + * JSONP:JAVADOC:406; JSONP:JAVADOC:408; JSONP:JAVADOC:409; JSONP:JAVADOC:491; + * JSONP:JAVADOC:492; JSONP:JAVADOC:494; JSONP:JAVADOC:495; JSONP:JAVADOC:497; + * JSONP:JAVADOC:498; JSONP:JAVADOC:500; JSONP:JAVADOC:501; JSONP:JAVADOC:507; + * + * @test_Strategy: Test JsonArray exception conditions. Trips the exceptions: + * java.lang.IndexOutOfBoundsException java.lang.ArithmeticException + * java.lang.NumberFormatException java.lang.ClassCastException + * java.lang.UnsupportedOperationException + */ + @Test + public void jsonArrayExceptionTests() throws Fault { + boolean pass = true; + JsonObject testObject = null; + JsonArray testArray = null; + + try { + System.out.println("Create sample JsonObject for testing"); + testObject = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create sample JsonArray for testing"); + testArray = JSONP_Util.createSampleJsonArray(); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to JsonNumber via getJsonNumber(int)"); + JsonNumber value = testArray.getJsonNumber(0); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonArray to JsonNumber via getJsonNumber(int)"); + JsonNumber value = testArray.getJsonNumber(15); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonNumber to JsonString via getJsonString(int)"); + JsonString value = testArray.getJsonString(4); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonString to JsonNumber via getJsonNumber(int)"); + JsonNumber value = testArray.getJsonNumber(6); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonValue.TRUE to JsonNumber via getJsonNumber(int)"); + JsonNumber value = testArray.getJsonNumber(1); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to JsonArray via getJsonArray(int)"); + JsonArray value = testArray.getJsonArray(0); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonArray to JsonObject via getJsonObject(int)"); + JsonObject value = testArray.getJsonObject(15); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to JsonNumber via getInt(int)"); + int value = testArray.getInt(0); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to JsonString via getString(int)"); + String value = testArray.getString(0); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonArray to JsonString via getString(int)"); + String value = testArray.getString(15); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to boolean via getBoolean(int)"); + boolean value = testArray.getBoolean(0); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonArray to boolean via getBoolean(int)"); + boolean value = testArray.getBoolean(13); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonString to boolean via getBoolean(int)"); + boolean value = testArray.getBoolean(6); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonNumber to boolean via getBoolean(int)"); + boolean value = testArray.getBoolean(4); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing -1 as index to getJsonNumber(int)"); + int myInt = testArray.getJsonNumber(-1).intValue(); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing 10000 as index to getJsonNumber(int)"); + JsonValue myJsonValue = testArray.getJsonNumber(10000); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing -1 as index to getJsonArray(int)"); + JsonValue myJsonValue = testArray.getJsonArray(-1); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing 10000 as index to getJsonArray(int)"); + JsonValue myJsonValue = testArray.getJsonArray(10000); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing -1 as index to getJsonObject(int)"); + JsonValue myJsonValue = testArray.getJsonObject(-1); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing 10000 as index to getJsonObject(int)"); + JsonValue myJsonValue = testArray.getJsonObject(10000); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing -1 as index to getJsonString(int)"); + JsonValue myJsonValue = testArray.getJsonString(-1); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing 10000 as index to getJsonString(int)"); + JsonValue myJsonValue = testArray.getJsonString(10000); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing -1 as index to getInt(int)"); + int myInt = testArray.getInt(-1); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing 10000 as index to getInt(int)"); + int myInt = testArray.getInt(10000); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing -1 as index to getString(int)"); + String myString = testArray.getString(-1); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing 10000 as index to getString(int)"); + String myString = testArray.getString(10000); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing -1 as index to getBoolean(int)"); + boolean myBoolean = testArray.getBoolean(-1); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing 10000 as index to getBoolean(int)"); + boolean myBoolean = testArray.getBoolean(10000); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing -1 as index to isNull(int)"); + boolean myBoolean = testArray.isNull(-1); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip IndexOutOfBoundsException + try { + System.out.println( + "Trip IndexOutOfBoundsException passing 10000 as index to isNull(int)"); + boolean myBoolean = testArray.isNull(10000); + pass = false; + System.err.println("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + System.out.println("Got expected IndexOutOfBoundsException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NumberFormatException calling add(Double.NaN) + try { + System.out.println("Trip NumberFormatException calling add(Double.NaN)"); + JsonArray array = Json.createArrayBuilder().add(Double.NaN).build(); + pass = false; + System.err.println("Failed to throw NumberFormatException"); + } catch (NumberFormatException e) { + System.out.println("Got expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NumberFormatException calling add(Double.NEGATIVE_INFINITY) + try { + System.out.println( + "Trip NumberFormatException calling add(Double.NEGATIVE_INFINITY)"); + JsonArray array = Json.createArrayBuilder().add(Double.NEGATIVE_INFINITY) + .build(); + pass = false; + System.err.println("Failed to throw NumberFormatException"); + } catch (NumberFormatException e) { + System.out.println("Got expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NumberFormatException calling add(Double.POSITIVE_INFINITY) + try { + System.out.println( + "Trip NumberFormatException calling add(Double.POSITIVE_INFINITY)"); + JsonArray array = Json.createArrayBuilder().add(Double.POSITIVE_INFINITY) + .build(); + pass = false; + System.err.println("Failed to throw NumberFormatException"); + } catch (NumberFormatException e) { + System.out.println("Got expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test for ArithmeticException + try { + System.out.println( + "Trip ArithmeticException calling add(12345.12345) and attempting to extract as an exact integer value"); + JsonArray array = Json.createArrayBuilder().add(12345.12345).build(); + System.out.println("Call JsonArray.getJsonNumber(0).intValueExact()"); + int value = array.getJsonNumber(0).intValueExact(); + pass = false; + System.err.println("Failed to throw ArithmeticException"); + } catch (ArithmeticException e) { + System.out.println("Got expected ArithmeticException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test for ArithmeticException + try { + System.out.println( + "Trip ArithmeticException calling add(12345.12345) and attempting to extract as an exact long value"); + JsonArray array = Json.createArrayBuilder().add(12345.12345).build(); + System.out.println("Call JsonArray.getJsonNumber(0).longValueExact()"); + long value = array.getJsonNumber(0).longValueExact(); + pass = false; + System.err.println("Failed to throw ArithmeticException"); + } catch (ArithmeticException e) { + System.out.println("Got expected ArithmeticException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test for ArithmeticException + try { + System.out.println( + "Trip ArithmeticException calling add(12345.12345) and attempting to extract as an exact biginteger value"); + JsonArray array = Json.createArrayBuilder().add(12345.12345).build(); + System.out.println("Call JsonArray.getJsonNumber(0).bigIntegerValueExact()"); + BigInteger value = array.getJsonNumber(0).bigIntegerValueExact(); + pass = false; + System.err.println("Failed to throw ArithmeticException"); + } catch (ArithmeticException e) { + System.out.println("Got expected ArithmeticException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Tests for UnsupportedOperationException using Collection methods to + // modify JsonArray List + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonArray.add(E) trying to modify JsonArray list which should be immutable"); + testArray.add(JsonValue.FALSE); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonArray.add(int,E) trying to modify JsonArray list which should be immutable"); + testArray.add(0, JsonValue.FALSE); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonArray.addAll(C) trying to modify JsonArray list which should be immutable"); + testArray.addAll(testArray); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonArray.addAll(int, C) trying to modify JsonArray list which should be immutable"); + testArray.addAll(0, testArray); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonArray.clear() trying to modify JsonArray list which should be immutable"); + testArray.clear(); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonArray.remove(int) trying to modify JsonArray list which should be immutable"); + testArray.remove(0); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonArray.removeAll(C) trying to modify JsonArray list which should be immutable"); + testArray.removeAll(testArray); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException trying to modify JsonArray list which should be immutable"); + testArray.remove(JsonValue.TRUE); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonArrayExceptionTests Failed"); + } + + /* + * @testName: jsonArrayNullValueExceptionTests + * + * @assertion_ids: JSONP:JAVADOC:555; JSONP:JAVADOC:556; JSONP:JAVADOC:557; + * JSONP:JAVADOC:558; JSONP:JAVADOC:559; JSONP:JAVADOC:560; + * + * @test_Strategy: Test JSON NPE exception conditions when attempting to add a + * specified value that is null. + */ + @Test + public void jsonArrayNullValueExceptionTests() throws Fault { + boolean pass = true; + JsonArrayBuilder jab = Json.createArrayBuilder(); + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonArrayBuilder.add(JsonValue) when JsonValue is null."); + jab.add((JsonValue) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + try { + System.out.println( + "Trip NullPointerException for JsonArrayBuilder.add(BigInteger) when BigInteger is null."); + jab.add((BigInteger) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + try { + System.out.println( + "Trip NullPointerException for JsonArrayBuilder.add(JsonArrayBuilder) when JsonArrayBuilder is null."); + jab.add((JsonArrayBuilder) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + try { + System.out.println( + "Trip NullPointerException for JsonArrayBuilder.add(JsonObjectBuilder) when JsonObjectBuilder is null."); + jab.add((JsonObjectBuilder) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + try { + System.out.println( + "Trip NullPointerException for JsonArrayBuilder.add(BigDecimal) when BigDecimal is null."); + jab.add((BigDecimal) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonArrayBuilder.add(String) when String is null."); + jab.add((String) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonArrayNullValueExceptionTests Failed"); + } + + /* + * @testName: jsonCreateArrayBuilder11Test + * + * @assertion_ids: JSONP:JAVADOC:572; JSONP:JAVADOC:573; JSONP:JAVADOC:651; + * JSONP:JAVADOC:652; + * + * @test_Strategy: Tests JsonArrayBuilder API factory methods added in JSON-P + * 1.1. + */ + @Test + public void jsonCreateArrayBuilder11Test() throws Fault { + ArrayBuilders createTest = new ArrayBuilders(); + final TestResult result = createTest.test(); + result.eval(); + } + + /* + * @testName: jsonArrayBuilder11AddTest + * + * @assertion_ids: JSONP:JAVADOC:589; JSONP:JAVADOC:590; JSONP:JAVADOC:591; + * JSONP:JAVADOC:592; JSONP:JAVADOC:593; JSONP:JAVADOC:594; JSONP:JAVADOC:595; + * JSONP:JAVADOC:596; JSONP:JAVADOC:597; JSONP:JAVADOC:598; JSONP:JAVADOC:599; + * JSONP:JAVADOC:600; JSONP:JAVADOC:601; + * + * @test_Strategy: Tests JsonArrayBuilder API add() methods added in JSON-P + * 1.1. + */ + @Test + public void jsonArrayBuilder11AddTest() throws Fault { + ArrayBuildAdd addTest = new ArrayBuildAdd(); + final TestResult result = addTest.test(); + result.eval(); + } + + /* + * @testName: jsonArrayBuilder11SetTest + * + * @assertion_ids: JSONP:JAVADOC:603; JSONP:JAVADOC:604; JSONP:JAVADOC:605; + * JSONP:JAVADOC:606; JSONP:JAVADOC:607; JSONP:JAVADOC:608; JSONP:JAVADOC:609; + * JSONP:JAVADOC:610; JSONP:JAVADOC:611; JSONP:JAVADOC:612; JSONP:JAVADOC:613; + * + * @test_Strategy: Tests JsonArrayBuilder API set() methods added in JSON-P + * 1.1. + */ + @Test + public void jsonArrayBuilder11SetTest() throws Fault { + ArrayBuildSet setTest = new ArrayBuildSet(); + final TestResult result = setTest.test(); + result.eval(); + } + + /* + * @testName: jsonArrayBuilder11RemoveTest + * + * @assertion_ids: JSONP:JAVADOC:602; + * + * @test_Strategy: Tests JsonArrayBuilder API remove() methods added in JSON-P + * 1.1. + */ + @Test + public void jsonArrayBuilder11RemoveTest() throws Fault { + ArrayBuildRemove removeTest = new ArrayBuildRemove(); + final TestResult result = removeTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonbuilderfactorytests/BuilderFactory.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonbuilderfactorytests/BuilderFactory.java new file mode 100644 index 0000000..0ba5076 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonbuilderfactorytests/BuilderFactory.java
@@ -0,0 +1,285 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonbuilderfactorytests; + +import jakarta.jsonp.tck.api.common.TestResult; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests for + * {@link JsonBuilderFactory}. + */ +public class BuilderFactory { + + + /** + * {@link JsonBuilderFactory} API methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonBuilderFactory API methods added in JSON-P 1.1."); + System.out.println("JsonBuilderFactory API methods added in JSON-P 1.1."); + testCreateArrayBuilderString(result); + testCreateArrayBuilderInt(result); + testCreateArrayBuilderBool(result); + testCreateArrayBuilderObject(result); + testCreateArrayBuilderNull(result); + testCreateObjectBuilderString(result); + testCreateObjectBuilderInt(result); + testCreateObjectBuilderBool(result); + testCreateObjectBuilderObject(result); + testCreateObjectBuilderNull(result); + return result; + } + + /** + * Test {@code JsonArrayBuilder createArrayBuilder(JsonArray)} method on + * {@code String} value. + * + * @param result + * Test suite result. + */ + private void testCreateArrayBuilderString(final TestResult result) { + System.out.println(" - createArrayBuilder(JsonArray) for String"); + final JsonArray in = createStringArray2(); + final JsonArray check = createStringArray2(); + verifyCreateArrayBuilder(result, check, in); + } + + /** + * Test {@code JsonArrayBuilder createArrayBuilder(JsonArray)} method on + * {@code int} value. + * + * @param result + * Test suite result. + */ + private void testCreateArrayBuilderInt(final TestResult result) { + System.out.println(" - createArrayBuilder(JsonArray) for int"); + final JsonArray in = createIntArray2(); + final JsonArray check = createIntArray2(); + verifyCreateArrayBuilder(result, check, in); + } + + /** + * Test {@code JsonArrayBuilder createArrayBuilder(JsonArray)} method on + * {@code boolean} value. + * + * @param result + * Test suite result. + */ + private void testCreateArrayBuilderBool(final TestResult result) { + System.out.println(" - createArrayBuilder(JsonArray) for boolean"); + final JsonArray in = createBoolArray2(); + final JsonArray check = createBoolArray2(); + verifyCreateArrayBuilder(result, check, in); + } + + /** + * Test {@code JsonArrayBuilder createArrayBuilder(JsonArray)} method on + * {@code JsonObject} value. + * + * @param result + * Test suite result. + */ + private void testCreateArrayBuilderObject(final TestResult result) { + System.out.println(" - createArrayBuilder(JsonArray) for JsonObject"); + final JsonArray in = createObjectArray2(); + final JsonArray check = createObjectArray2(); + verifyCreateArrayBuilder(result, check, in); + } + + /** + * Test {@code JsonArrayBuilder createArrayBuilder(JsonArray)} method on + * {@code null} value. Method shall throw NullPointerException. + * + * @param result + * Test suite result. + */ + private void testCreateArrayBuilderNull(final TestResult result) { + System.out.println(" - createArrayBuilder(JsonArray) for null"); + final JsonArray in = null; + final JsonBuilderFactory factory = Json.createBuilderFactory(null); + try { + factory.createArrayBuilder(in); + result.fail("createArrayBuilder(JsonArray)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println( + " - Expected exception for null argument: " + e.getMessage()); + } catch (Throwable t) { + result.fail("createObjectBuilder(JsonObject)", + "Calling method with with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Test {@code JsonObjectBuilder createObjectBuilder(JsonObject)} method on + * {@code String} value. + * + * @param result + * Test suite result. + */ + private void testCreateObjectBuilderString(final TestResult result) { + System.out.println(" - createObjectBuilder(JsonObject) for String"); + final JsonObject in = createSimpleObjectStr(); + final JsonObject check = createSimpleObjectStr(); + verifyCreateObjectBuilder(result, check, in); + } + + /** + * Test {@code JsonObjectBuilder createObjectBuilder(JsonObject)} method on + * {@code int} value. + * + * @param result + * Test suite result. + */ + private void testCreateObjectBuilderInt(final TestResult result) { + System.out.println(" - createObjectBuilder(JsonObject) for int"); + final JsonObject in = createSimpleObjectInt(); + final JsonObject check = createSimpleObjectInt(); + verifyCreateObjectBuilder(result, check, in); + } + + /** + * Test {@code JsonObjectBuilder createObjectBuilder(JsonObject)} method on + * {@code boolean} value. + * + * @param result + * Test suite result. + */ + private void testCreateObjectBuilderBool(final TestResult result) { + System.out.println(" - createObjectBuilder(JsonObject) for boolean"); + final JsonObject in = createSimpleObjectBool(); + final JsonObject check = createSimpleObjectBool(); + verifyCreateObjectBuilder(result, check, in); + } + + /** + * Test {@code JsonObjectBuilder createObjectBuilder(JsonObject)} method on + * {@code JsonObject} value. + * + * @param result + * Test suite result. + */ + private void testCreateObjectBuilderObject(final TestResult result) { + System.out.println(" - createObjectBuilder(JsonObject) for JsonObject"); + final JsonObject in = createSimpleObjectObject(); + final JsonObject check = createSimpleObjectObject(); + verifyCreateObjectBuilder(result, check, in); + } + + /** + * Test helper: Verify {@code JsonArrayBuilder createArrayBuilder(JsonArray)} + * method on provided array. + * + * @param result + * Test suite result. + * @param check + * Expected value (used for operation check). + * @param in + * JSON array to pass to the method. + */ + private void verifyCreateArrayBuilder(final TestResult result, + final JsonArray check, final JsonArray in) { + final JsonBuilderFactory factory = Json.createBuilderFactory(null); + final JsonArrayBuilder builder = factory.createArrayBuilder(in); + final JsonArray out = builder.build(); + if (operationFailed(check, out)) { + result.fail("createArrayBuilder(JsonArray)", "Output builder " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Test helper: Verify + * {@code JsonObjectBuilder createObjectBuilder(JsonObjecty)} method on + * provided object. + * + * @param result + * Test suite result. + * @param check + * Expected value (used for operation check). + * @param in + * JSON object to pass to the method. + */ + private void verifyCreateObjectBuilder(final TestResult result, + final JsonObject check, final JsonObject in) { + System.out.println(" - IN: " + valueToString(in)); + final JsonBuilderFactory factory = Json.createBuilderFactory(null); + final JsonObjectBuilder builder = factory.createObjectBuilder(in); + final JsonObject out = builder.build(); + if (operationFailed(check, out)) { + result.fail("createObjectBuilder(JsonObject)", "Output builder " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Test {@code JsonObjectBuilder createObjectBuilder(JsonObject)} method on + * {@code null} value. Method shall throw NullPointerException. + * + * @param result + * Test suite result. + */ + private void testCreateObjectBuilderNull(final TestResult result) { + System.out.println(" - createObjectBuilder(JsonObject) for null"); + final JsonObject in = null; + final JsonBuilderFactory factory = Json.createBuilderFactory(null); + try { + factory.createObjectBuilder(in); + result.fail("createObjectBuilder(JsonObject)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println( + " - Expected exception for null argument: " + e.getMessage()); + } catch (Throwable t) { + result.fail("createObjectBuilder(JsonObject)", + "Calling method with with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonbuilderfactorytests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonbuilderfactorytests/ClientTests.java new file mode 100644 index 0000000..94ad80c --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonbuilderfactorytests/ClientTests.java
@@ -0,0 +1,157 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonbuilderfactorytests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +import java.util.Map; +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.json.*; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonBuilderFactoryTest1 + * + * @assertion_ids: JSONP:JAVADOC:445; JSONP:JAVADOC:453; JSONP:JAVADOC:454; + * JSONP:JAVADOC:455; + * + * @test_Strategy: Tests the JsonBuilderFactory API. + * + * JsonBuilderFactory builderFactory = Json.createBuilderFactory(Map<String, + * ?>); JsonArray array = builderFactory.createArrayBuilder() JsonObject + * object = builderFactory.createObjectBuilder() + */ + @Test + public void jsonBuilderFactoryTest1() throws Fault { + boolean pass = true; + try { + System.out.println("Create JsonBuilderFactory with Map<String, ?> with EMPTY config"); + JsonBuilderFactory builderFactory = Json + .createBuilderFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = builderFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("---------------------------------------------------"); + System.out.println("TEST CASE [JsonBuilderFactory.createArrayBuilder()]"); + System.out.println("---------------------------------------------------"); + System.out.println("Create JsonArrayBuilder using JsonBuilderFactory"); + JsonArray expJsonArray = JSONP_Util.createJsonArrayFromString("[0,2]"); + JsonArray actJsonArray = builderFactory.createArrayBuilder().add(0).add(2) + .build(); + if (!JSONP_Util.assertEqualsJsonArrays(expJsonArray, actJsonArray)) + pass = false; + + System.out.println("----------------------------------------------------"); + System.out.println("TEST CASE [JsonBuilderFactory.createObjectBuilder()]"); + System.out.println("----------------------------------------------------"); + System.out.println("Create JsonObjectBuilder using JsonBuilderFactory"); + JsonObject expJsonObject = JSONP_Util + .createJsonObjectFromString("{\"foo\":\"bar\"}"); + JsonObject actJsonObject = builderFactory.createObjectBuilder() + .add("foo", "bar").build(); + if (!JSONP_Util.assertEqualsJsonObjects(expJsonObject, actJsonObject)) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonBuilderFactoryTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonBuilderFactoryTest1 Failed"); + } + + /* + * @testName: jsonBuilderFactoryTest2 + * + * @assertion_ids: JSONP:JAVADOC:445; JSONP:JAVADOC:455; + * + * @test_Strategy: Tests the JsonBuilderFactory API. + * + * JsonBuilderFactory builderFactory = Json.createBuilderFactory(Map<String, + * ?>); Map<String, ?> config = JsonBuilderFactory.getConfigInUse(); + * + * Test for the following 3 scenarios: 1) no supported provider property + * (empty config) 2) non supported provider property + */ + @Test + public void jsonBuilderFactoryTest2() throws Fault { + boolean pass = true; + JsonBuilderFactory builderFactory; + Map<String, ?> config; + try { + System.out.println("----------------------------------------------"); + System.out.println("Test scenario1: no supported provider property"); + System.out.println("----------------------------------------------"); + System.out.println("Create JsonBuilderFactory with Map<String, ?> with EMPTY config"); + builderFactory = Json.createBuilderFactory(JSONP_Util.getEmptyConfig()); + config = builderFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("-----------------------------------------------"); + System.out.println("Test scenario2: non supported provider property"); + System.out.println("-----------------------------------------------"); + System.out.println("Create JsonBuilderFactory with Map<String, ?> with FOO config"); + builderFactory = Json.createBuilderFactory(JSONP_Util.getFooConfig()); + config = builderFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonBuilderFactoryTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonBuilderFactoryTest2 Failed"); + } + + /* + * @testName: jsonBuilderFactory11Test + * + * @assertion_ids: JSONP:JAVADOC:614; JSONP:JAVADOC:615; + * + * @test_Strategy: Tests JsonBuilderFactory API methods added in JSON-P 1.1. + */ + @Test + public void jsonBuilderFactory11Test() throws Fault { + BuilderFactory factoryTest = new BuilderFactory(); + final TestResult result = factoryTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsoncoding/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsoncoding/ClientTests.java new file mode 100644 index 0000000..cecc832 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsoncoding/ClientTests.java
@@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsoncoding; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.json.Json; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonEncodeTest + * + * @assertion_ids: JSONP:JAVADOC:681; JSONP:JAVADOC:682; + * + * @test_Strategy: Encode and decode Json Pointer as defined by RFC 6901 + */ + @Test + public void jsonEncodeTest() throws Fault { + String DECODED = "/a/~b/c"; + String ENCODED = "~1a~1~0b~1c"; + StringBuilder error = new StringBuilder(); + System.out.println("----------------------------------------------"); + System.out.println("Test encode " + DECODED); + System.out.println("----------------------------------------------"); + String encoded = Json.encodePointer(DECODED); + if (!ENCODED.equals(encoded)) + error.append("The pointer ").append(DECODED) + .append(" has been encoded as ").append(encoded).append('\n'); + + System.out.println("----------------------------------------------"); + System.out.println("Test decode " + ENCODED); + String decoded = Json.decodePointer(ENCODED); + if (!DECODED.equals(decoded)) + error.append("The pointer ").append(ENCODED) + .append(" has been decoded as ").append(decoded).append('\n'); + if (error.length() != 0) + throw new Fault(error.toString()); + System.out.println("----------------------------------------------"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsongeneratorfactorytests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsongeneratorfactorytests/ClientTests.java new file mode 100644 index 0000000..af39a34 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsongeneratorfactorytests/ClientTests.java
@@ -0,0 +1,336 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsongeneratorfactorytests; + +import jakarta.json.*; +import jakarta.json.stream.*; + +import java.io.*; +import java.nio.charset.Charset; + +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; +import java.util.Iterator; +import java.util.Map; +import java.util.ArrayList; + +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonGeneratorFactoryTest1 + * + * @assertion_ids: JSONP:JAVADOC:162; JSONP:JAVADOC:416; JSONP:JAVADOC:427; + * + * @test_Strategy: Tests the JsonGeneratorFactory API. + * + * JsonGeneratorFactory generatorFactory = + * Json.createGeneratorFactory(Map<String, ?>); JsonGenerator generator1 = + * generatorFactory.createGenerator(Writer) JsonGenerator generator2 = + * generatorFactory.createGenerator(Writer) + */ + @Test + public void jsonGeneratorFactoryTest1() throws Fault { + boolean pass = true; + JsonGenerator generator1 = null; + JsonGenerator generator2 = null; + String expString; + String actString; + try { + System.out.println( + "Create JsonGeneratorFactory with Map<String, ?> with PRETTY_PRINTING config"); + JsonGeneratorFactory generatorFactory = Json + .createGeneratorFactory(JSONP_Util.getPrettyPrintingConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = generatorFactory.getConfigInUse(); + String[] props = { JsonGenerator.PRETTY_PRINTING, }; + if (!JSONP_Util.doConfigCheck(config, 1, props)) + pass = false; + System.out.println("--------------------------------------------------------"); + System.out.println("TEST CASE [JsonGeneratorFactory.createGenerator(Writer)]"); + System.out.println("--------------------------------------------------------"); + System.out.println("Create 1st JsonGenerator using JsonGeneratorFactory"); + StringWriter sWriter1 = new StringWriter(); + generator1 = generatorFactory.createGenerator(sWriter1); + if (generator1 == null) { + System.err.println("GeneratorFactory failed to create generator1"); + pass = false; + } else { + generator1.writeStartObject().writeEnd(); + generator1.close(); + } + System.out.println("sWriter1=" + sWriter1.toString()); + expString = "{}"; + actString = JSONP_Util.removeWhitespace(sWriter1.toString()); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + System.out.println("Create 2nd JsonGenerator using JsonGeneratorFactory"); + StringWriter sWriter2 = new StringWriter(); + generator2 = generatorFactory.createGenerator(sWriter2); + if (generator2 == null) { + System.err.println("GeneratorFactory failed to create generator2"); + pass = false; + } else { + generator2.writeStartArray().writeEnd(); + generator2.close(); + } + System.out.println("sWriter2=" + sWriter2.toString()); + expString = "[]"; + actString = JSONP_Util.removeWhitespace(sWriter2.toString()); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonGeneratorFactoryTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorFactoryTest1 Failed"); + } + + /* + * @testName: jsonGeneratorFactoryTest2 + * + * @assertion_ids: JSONP:JAVADOC:163; JSONP:JAVADOC:416; JSONP:JAVADOC:427; + * + * @test_Strategy: Tests the JsonGeneratorFactory API. + * + * JsonGeneratorFactory generatorFactory = + * Json.createGeneratorFactory(Map<String,?>); JsonGenerator generator1 = + * generatorFactory.createGenerator(OutputStream, Charset) JsonGenerator + * generator2 = generatorFactory.createGenerator(OutputStream, Charset) + * + * Create generator with both UTF-8 and UTF-16BE. + */ + @Test + public void jsonGeneratorFactoryTest2() throws Fault { + boolean pass = true; + JsonGenerator generator1 = null; + JsonGenerator generator2 = null; + String expString, actString; + try { + System.out.println( + "Create JsonGeneratorFactory with Map<String, ?> with PRETTY_PRINTING config"); + JsonGeneratorFactory generatorFactory = Json + .createGeneratorFactory(JSONP_Util.getPrettyPrintingConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = generatorFactory.getConfigInUse(); + String[] props = { JsonGenerator.PRETTY_PRINTING, }; + if (!JSONP_Util.doConfigCheck(config, 1, props)) + pass = false; + + System.out.println( + "-----------------------------------------------------------------------"); + System.out.println( + "TEST CASE [JsonGeneratorFactory.createGenerator(OutputStream, Charset)]"); + System.out.println( + "-----------------------------------------------------------------------"); + System.out.println( + "Create 1st JsonGenerator using JsonGeneratorFactory with UTF-8 encoding"); + ByteArrayOutputStream baos1 = new ByteArrayOutputStream(); + generator1 = generatorFactory.createGenerator(baos1, JSONP_Util.UTF_8); + if (generator1 == null) { + System.err.println("GeneratorFactory failed to create generator1"); + pass = false; + } else { + generator1.writeStartObject().writeEnd(); + generator1.close(); + } + System.out.println("baos1=" + baos1.toString("UTF-8")); + expString = "{}"; + actString = JSONP_Util.removeWhitespace(baos1.toString("UTF-8")); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + System.out.println( + "Create 2nd JsonGenerator using JsonGeneratorFactory with UTF-16BE encoding"); + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + generator2 = generatorFactory.createGenerator(baos2, JSONP_Util.UTF_16BE); + if (generator2 == null) { + System.err.println("GeneratorFactory failed to create generator2"); + pass = false; + } else { + generator2.writeStartArray().writeEnd(); + generator2.close(); + } + System.out.println("baos2=" + baos2.toString("UTF-16BE")); + expString = "[]"; + actString = JSONP_Util.removeWhitespace(baos2.toString("UTF-16BE")); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonGeneratorFactoryTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorFactoryTest2 Failed"); + } + + /* + * @testName: jsonGeneratorFactoryTest3 + * + * @assertion_ids: JSONP:JAVADOC:200; JSONP:JAVADOC:416; JSONP:JAVADOC:427; + * + * @test_Strategy: Tests the JsonGeneratorFactory API. + * + * JsonGeneratorFactory generatorFactory = + * Json.createGeneratorFactory(Map<String, ?>); JsonGenerator generator1 = + * generatorFactory.createGenerator(OutputStream) JsonGenerator generator2 = + * generatorFactory.createGenerator(OutputStream) + */ + @Test + public void jsonGeneratorFactoryTest3() throws Fault { + boolean pass = true; + JsonGenerator generator1 = null; + JsonGenerator generator2 = null; + String expString; + String actString; + try { + System.out.println( + "Create JsonGeneratorFactory with Map<String, ?> with PRETTY_PRINTING config"); + JsonGeneratorFactory generatorFactory = Json + .createGeneratorFactory(JSONP_Util.getPrettyPrintingConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = generatorFactory.getConfigInUse(); + String[] props = { JsonGenerator.PRETTY_PRINTING, }; + if (!JSONP_Util.doConfigCheck(config, 1, props)) + pass = false; + System.out.println( + "-----------------------------------------------------------------"); + System.out.println( + "TEST CASE [JsonGeneratorFactory.createGenerator(OutputStream os)]"); + System.out.println( + "-----------------------------------------------------------------"); + System.out.println("Create 1st JsonGenerator using JsonGeneratorFactory"); + ByteArrayOutputStream baos1 = new ByteArrayOutputStream(); + generator1 = generatorFactory.createGenerator(baos1); + if (generator1 == null) { + System.err.println("GeneratorFactory failed to create generator1"); + pass = false; + } else { + generator1.writeStartObject().writeEnd(); + generator1.close(); + } + System.out.println("baos1=" + baos1.toString("UTF-8")); + expString = "{}"; + actString = JSONP_Util.removeWhitespace(baos1.toString("UTF-8")); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + System.out.println("Create 2nd JsonGenerator using JsonGeneratorFactory"); + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + generator2 = generatorFactory.createGenerator(baos2); + if (generator2 == null) { + System.err.println("GeneratorFactory failed to create generator2"); + pass = false; + } else { + generator2.writeStartArray().writeEnd(); + generator2.close(); + } + System.out.println("baos2=" + baos2.toString("UTF-8")); + expString = "[]"; + actString = JSONP_Util.removeWhitespace(baos2.toString("UTF-8")); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonGeneratorFactoryTest3 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorFactoryTest3 Failed"); + } + + /* + * @testName: jsonGeneratorFactoryTest4 + * + * @assertion_ids: JSONP:JAVADOC:416; JSONP:JAVADOC:427; + * + * @test_Strategy: Tests the JsonGeneratorFactory API. + * + * JsonGeneratorFactory generatorFactory = + * Json.createGeneratorFactory(Map<String, ?>); Map<String, ?> config = + * JsonGeneratorFactory.getConfigInUse(); + * + * Test for the following 3 scenarios: 1) no supported provider property + * (empty config) 2) supported provider property 3) supported and non + * supported provider property + */ + @Test + public void jsonGeneratorFactoryTest4() throws Fault { + boolean pass = true; + JsonGeneratorFactory generatorFactory; + Map<String, ?> config; + try { + System.out.println("----------------------------------------------"); + System.out.println("Test scenario1: no supported provider property"); + System.out.println("----------------------------------------------"); + System.out.println( + "Create JsonGeneratorFactory with Map<String, ?> with EMPTY config"); + generatorFactory = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()); + config = generatorFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("-------------------------------------------"); + System.out.println("Test scenario2: supported provider property"); + System.out.println("-------------------------------------------"); + System.out.println( + "Create JsonGeneratorFactory with Map<String, ?> with PRETTY_PRINTING config"); + generatorFactory = Json + .createGeneratorFactory(JSONP_Util.getPrettyPrintingConfig()); + config = generatorFactory.getConfigInUse(); + String[] props = { JsonGenerator.PRETTY_PRINTING, }; + if (!JSONP_Util.doConfigCheck(config, 1, props)) + pass = false; + + System.out.println("-------------------------------------------------------------"); + System.out.println("Test scenario3: supported and non supported provider property"); + System.out.println("-------------------------------------------------------------"); + System.out.println("Create JsonGeneratorFactory with Map<String, ?> with all config"); + generatorFactory = Json.createGeneratorFactory(JSONP_Util.getAllConfig()); + config = generatorFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 1, props)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonGeneratorFactoryTest4 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorFactoryTest4 Failed"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsongeneratortests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsongeneratortests/ClientTests.java new file mode 100644 index 0000000..616dece --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsongeneratortests/ClientTests.java
@@ -0,0 +1,2142 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsongeneratortests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.json.*; +import jakarta.json.stream.*; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* private Utility methods */ + + /********************************************************************************* + * generateSimpleJsonObject + *********************************************************************************/ + private void generateSimpleJsonObject(JsonGenerator generator) { + try { + generator.writeStartObject().writeStartObject("object") + .write("string", "string").write("number", 1) + .write("true", JsonValue.TRUE).write("false", JsonValue.FALSE) + .write("null", JsonValue.NULL).writeEnd().writeStartArray("array") + .write("string").write(1).write(JsonValue.TRUE).write(JsonValue.FALSE) + .write(JsonValue.NULL).writeEnd().writeEnd(); + generator.close(); + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + } + } + + /********************************************************************************* + * generateSimpleJsonArray + *********************************************************************************/ + private void generateSimpleJsonArray(JsonGenerator generator) { + try { + generator.writeStartArray().writeStartObject().write("string", "string") + .write("number", 1).write("true", JsonValue.TRUE) + .write("false", JsonValue.FALSE).write("null", JsonValue.NULL) + .writeEnd().writeStartArray().write("string").write(1) + .write(JsonValue.TRUE).write(JsonValue.FALSE).write(JsonValue.NULL) + .writeEnd().writeEnd(); + generator.close(); + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + } + } + + /********************************************************************************* + * generateJsonObject + *********************************************************************************/ + private String generateJsonObject() { + try { + System.out.println("Generate a JsonObject"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write("emptyString", "") + .writeStartArray("emptyArray").writeEnd() + .writeStartObject("emptyObject").writeEnd().write("string", "string") + .write("intMin", Integer.MIN_VALUE).write("intMax", Integer.MAX_VALUE) + .write("longMin", Long.MIN_VALUE).write("longMax", Long.MAX_VALUE) + .write("doubleMin", Double.MIN_VALUE) + .write("doubleMax", Double.MAX_VALUE) + .write("bigInteger", + new BigInteger(Integer.toString(Integer.MAX_VALUE))) + .write("bigDecimal", BigDecimal.valueOf(Integer.MIN_VALUE)) + .write("true", JsonValue.TRUE).write("false", JsonValue.FALSE) + .write("null", JsonValue.NULL).writeStartObject("object") + .write("emptyString", "").writeStartArray("emptyArray").writeEnd() + .writeStartObject("emptyObject").writeEnd().write("string", "string") + .write("number", 100).write("true", true).write("false", false) + .writeNull("null").writeStartObject("object").write("name", "value") + .write("objectFooBar", JSONP_Util.buildJsonObjectFooBar()) + .write("arrayFooBar", JSONP_Util.buildJsonArrayFooBar()).writeEnd() + .writeStartArray("array").write("one").write("two") + .write(JSONP_Util.buildJsonObjectFooBar()) + .write(JSONP_Util.buildJsonArrayFooBar()).writeEnd().writeEnd() + .writeStartArray("array").write("string").write(Integer.MAX_VALUE) + .write(Long.MAX_VALUE).write(Double.MAX_VALUE) + .write(new BigInteger(Integer.toString(Integer.MAX_VALUE))) + .write(JsonValue.TRUE).write(JsonValue.FALSE).write(JsonValue.NULL) + .writeStartObject().write("name", "value").writeEnd() + .writeStartArray().write("one").write("two").writeEnd().writeEnd() + .write("asciiChars", + "\\\"\\\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") + .writeEnd(); + generator.close(); + return sWriter.toString(); + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + return null; + } + } + + /********************************************************************************* + * buildJsonObject + *********************************************************************************/ + private JsonObject buildJsonObject() { + try { + System.out.println("Build a JsonObject"); + JsonObject jsonObject = Json.createObjectBuilder().add("emptyString", "") + .add("emptyArray", Json.createArrayBuilder()) + .add("emptyObject", Json.createObjectBuilder()) + .add("string", "string").add("intMin", Integer.MIN_VALUE) + .add("intMax", Integer.MAX_VALUE).add("longMin", Long.MIN_VALUE) + .add("longMax", Long.MAX_VALUE).add("doubleMin", Double.MIN_VALUE) + .add("doubleMax", Double.MAX_VALUE) + .add("bigInteger", + new BigInteger(Integer.toString(Integer.MAX_VALUE))) + .add("bigDecimal", BigDecimal.valueOf(Integer.MIN_VALUE)) + .add("true", JsonValue.TRUE).add("false", JsonValue.FALSE) + .add("null", JsonValue.NULL) + .add("object", + Json.createObjectBuilder().add("emptyString", "") + .add("emptyArray", Json.createArrayBuilder()) + .add("emptyObject", Json.createObjectBuilder()) + .add("string", "string").add("number", 100) + .add("true", JsonValue.TRUE).add("false", JsonValue.FALSE) + .add("null", JsonValue.NULL) + .add("object", Json.createObjectBuilder().add("name", "value") + .add("objectFooBar", JSONP_Util.buildJsonObjectFooBar()) + .add("arrayFooBar", JSONP_Util.buildJsonArrayFooBar())) + .add("array", + Json.createArrayBuilder().add("one").add("two") + .add(JSONP_Util.buildJsonObjectFooBar()) + .add(JSONP_Util.buildJsonArrayFooBar()))) + .add("array", + Json.createArrayBuilder().add("string").add(Integer.MAX_VALUE) + .add(Long.MAX_VALUE).add(Double.MAX_VALUE) + .add(new BigInteger(Integer.toString(Integer.MAX_VALUE))) + .add(JsonValue.TRUE).add(JsonValue.FALSE).add(JsonValue.NULL) + .add(Json.createObjectBuilder().add("name", "value")) + .add(Json.createArrayBuilder().add("one").add("two"))) + .add("asciiChars", + "\\\"\\\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") + .build(); + return jsonObject; + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + return null; + } + } + + /********************************************************************************* + * generateJsonArray + *********************************************************************************/ + private String generateJsonArray() { + try { + System.out.println("Generate a JsonArray"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("").writeStartArray().writeEnd() + .writeStartObject().writeEnd().write("string") + .write(Integer.MIN_VALUE).write(Integer.MAX_VALUE) + .write(Long.MIN_VALUE).write(Long.MAX_VALUE).write(Double.MIN_VALUE) + .write(Double.MAX_VALUE) + .write(new BigInteger(new Integer(Integer.MAX_VALUE).toString())) + .write(BigDecimal.valueOf(Integer.MIN_VALUE)).write(JsonValue.TRUE) + .write(JsonValue.FALSE).write(JsonValue.NULL).writeStartObject() + .write("emptyString", "").writeStartArray("emptyArray").writeEnd() + .writeStartObject("emptyObject").writeEnd().write("string", "string") + .write("number", 100).write("true", JsonValue.TRUE) + .write("false", JsonValue.FALSE).write("null", JsonValue.NULL) + .writeStartObject("object").write("name", "value") + .write("objectFooBar", JSONP_Util.buildJsonObjectFooBar()) + .write("arrayFooBar", JSONP_Util.buildJsonArrayFooBar()).writeEnd() + .writeStartArray("array").write("one").write("two") + .write(JSONP_Util.buildJsonObjectFooBar()) + .write(JSONP_Util.buildJsonArrayFooBar()).writeEnd().writeEnd() + .writeStartArray().write("string").write(Integer.MAX_VALUE) + .write(Long.MAX_VALUE).write(Double.MAX_VALUE) + .write(new BigInteger(new Integer(Integer.MAX_VALUE).toString())) + .write(true).write(false).writeNull().writeStartObject() + .write("name", "value").writeEnd().writeStartArray().write("one") + .write("two").writeEnd().writeEnd() + .write( + "\\\"\\\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") + .writeEnd(); + generator.close(); + return sWriter.toString(); + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + return null; + } + } + + /********************************************************************************* + * buildJsonArray + *********************************************************************************/ + private JsonArray buildJsonArray() { + try { + System.out.println("Build a JsonArray"); + JsonArray jsonArray = Json.createArrayBuilder().add("") + .add(Json.createArrayBuilder()).add(Json.createObjectBuilder()) + .add("string").add(Integer.MIN_VALUE).add(Integer.MAX_VALUE) + .add(Long.MIN_VALUE).add(Long.MAX_VALUE).add(Double.MIN_VALUE) + .add(Double.MAX_VALUE) + .add(new BigInteger(new Integer(Integer.MAX_VALUE).toString())) + .add(BigDecimal.valueOf(Integer.MIN_VALUE)).add(JsonValue.TRUE) + .add(JsonValue.FALSE).add(JsonValue.NULL) + .add(Json.createObjectBuilder().add("emptyString", "") + .add("emptyArray", Json.createArrayBuilder()) + .add("emptyObject", Json.createObjectBuilder()) + .add("string", "string").add("number", 100) + .add("true", JsonValue.TRUE).add("false", JsonValue.FALSE) + .add("null", JsonValue.NULL) + .add("object", + Json.createObjectBuilder().add("name", "value") + .add("objectFooBar", JSONP_Util.buildJsonObjectFooBar()) + .add("arrayFooBar", JSONP_Util.buildJsonArrayFooBar())) + .add("array", + Json.createArrayBuilder().add("one").add("two") + .add(JSONP_Util.buildJsonObjectFooBar()) + .add(JSONP_Util.buildJsonArrayFooBar()))) + .add(Json.createArrayBuilder().add("string").add(Integer.MAX_VALUE) + .add(Long.MAX_VALUE).add(Double.MAX_VALUE) + .add(new BigInteger(new Integer(Integer.MAX_VALUE).toString())) + .add(JsonValue.TRUE).add(JsonValue.FALSE).add(JsonValue.NULL) + .add(Json.createObjectBuilder().add("name", "value")) + .add(Json.createArrayBuilder().add("one").add("two"))) + .add( + "\\\"\\\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") + .build(); + return jsonArray; + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + return null; + } + } + + /* Tests */ + + /* + * @testName: jsonGeneratorObjectTest1 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:131; + * JSONP:JAVADOC:289; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonObject. + * The output is written to a writer, read back as a string and filtered to + * remove whitespace and is compared against an expected string. + * + * { "object":{"string":"string","number":1,"true":true,"false":false,"null": + * null}, "array":["string", 1, true, false, null] } + */ + @Test + public void jsonGeneratorObjectTest1() throws Fault { + boolean pass = true; + try { + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generateSimpleJsonObject(generator); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "{\"object\":{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},\"array\":[\"string\",1,true,false,null]}"; + System.out.println("Read the JSON text back from Writer removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(sWriter.toString()); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorObjectTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorObjectTest1 Failed"); + } + + /* + * @testName: jsonGeneratorObjectTest2 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:168; + * JSONP:JAVADOC:289; JSONP:JAVADOC:307; JSONP:JAVADOC:327; JSONP:JAVADOC:339; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonObject. + * The output is written to a writer, read back as a string and filtered to + * remove whitespace and is compared against an expected string. + * + * { "emptyString":"", "emptyArray":[], "emptyObject":{}, "string":"string","+ + * "intMin":Integer.MIN_VALUE, "intMax":Integer.MAX_VALUE, + * "longMin":Long.MIN_VALUE, "longMax":Long.MAX_VALUE, "true":true, + * "false":false, "null":null, "object": { "emptyString":"", "emptyArray":[], + * "emptyObject":{}, "string":"string", "number":100, "true":true, + * "false":false, "null":null, "object":{"name":"value"} "array":["one","two"] + * }, "array": [ "string", Integer.MAX_VALUE, Long.MAX_VALUE, true, false, + * null, {"name":"value"}, ["one","two"] ], + * "asciiChars":"\"\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" + * } + */ + @Test + public void jsonGeneratorObjectTest2() throws Fault { + boolean pass = true; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json.createGenerator(baos); + generator.writeStartObject().write("emptyString", "") + .writeStartArray("emptyArray").writeEnd() + .writeStartObject("emptyObject").writeEnd().write("string", "string") + .write("intMin", Integer.MIN_VALUE).write("intMax", Integer.MAX_VALUE) + .write("longMin", Long.MIN_VALUE).write("longMax", Long.MAX_VALUE) + .write("true", JsonValue.TRUE).write("false", JsonValue.FALSE) + .write("null", JsonValue.NULL).writeStartObject("object") + .write("emptyString", "").writeStartArray("emptyArray").writeEnd() + .writeStartObject("emptyObject").writeEnd().write("string", "string") + .write("number", 100).write("true", JsonValue.TRUE) + .write("false", JsonValue.FALSE).write("null", JsonValue.NULL) + .writeStartObject("object").write("name", "value").writeEnd() + .writeStartArray("array").write("one").write("two").writeEnd() + .writeEnd().writeStartArray("array").write("string") + .write(Integer.MAX_VALUE).write(Long.MAX_VALUE).write(JsonValue.TRUE) + .write(JsonValue.FALSE).write(JsonValue.NULL).writeStartObject() + .write("name", "value").writeEnd().writeStartArray().write("one") + .write("two").writeEnd().writeEnd() + .write("asciiChars", + "\\\"\\\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") + .writeEnd(); + generator.close(); + + System.out.println("Dump of string: " + baos.toString("UTF-8")); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "{\"emptyString\":\"\",\"emptyArray\":[],\"emptyObject\":{},\"string\":\"string\"," + + "\"intMin\":" + Integer.MIN_VALUE + "," + "\"intMax\":" + + Integer.MAX_VALUE + "," + "\"longMin\":" + Long.MIN_VALUE + "," + + "\"longMax\":" + Long.MAX_VALUE + "," + + "\"true\":true,\"false\":false,\"null\":null,\"object\":{\"emptyString\":\"\",\"emptyArray\":[]," + + "\"emptyObject\":{},\"string\":\"string\",\"number\":100,\"true\":true,\"false\":false," + + "\"null\":null,\"object\":{\"name\":\"value\"}," + + "\"array\":[\"one\",\"two\"]},\"array\":[\"string\"," + + Integer.MAX_VALUE + "," + Long.MAX_VALUE + ",true,false,null," + + "{\"name\":\"value\"},[\"one\",\"two\"]],\"asciiChars\":" + + "\"\\\\\\\"\\\\\\\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM\"" + + "}"; + + System.out.println("Read the JSON text back from OutputStream removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-8")); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorObjectTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorObjectTest2 Failed"); + } + + /* + * @testName: jsonGeneratorObjectTest3 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:131; + * JSONP:JAVADOC:289; JSONP:JAVADOC:307; JSONP:JAVADOC:327; JSONP:JAVADOC:339; + * JSONP:JAVADOC:301; JSONP:JAVADOC:310; JSONP:JAVADOC:329; JSONP:JAVADOC:323; + * JSONP:JAVADOC:298; JSONP:JAVADOC:314; JSONP:JAVADOC:334; + * + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonObject. + * The output is written to a writer, read back as a JsonObject and compared + * against an expected JsonObject. + * + * { "emptyString":"", "emptyArray":[], "emptyObject":{}, "string":"string","+ + * "intMin":Integer.MIN_VALUE, "intMax":Integer.MAX_VALUE, + * "longMin":Long.MIN_VALUE, "longMax":Long.MAX_VALUE, + * "doubleMin":Double.MIN_VALUE, "doubleMax":Double.MAX_VALUE, + * "bigInteger":Integer.MAX_VALUE, "bigDecimal":Integer.MIN_VALUE, + * "true":true, "false":false, "null":null, "object": { "emptyString":"", + * "emptyArray":[], "emptyObject":{}, "string":"string", "number":100, + * "true":true, "false":false, "null":null, + * "object":{"name":"value",{"foo":"bar"}}, + * "array":["one","two",["foo","bar"]] }, "array": [ "string", + * Integer.MAX_VALUE, Long.MAX_VALUE, Double.MAX_VALUE, Integer.MAX_VALUE + * true, false, null, {"name":"value"}, ["one","two"] ], + * "asciiChars":"\\\"\\\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" + * } + */ + @Test + public void jsonGeneratorObjectTest3() throws Fault { + boolean pass = true; + try { + JsonObject expJsonObject = buildJsonObject(); + String jsonText = generateJsonObject(); + + JsonReader reader = Json.createReader(new StringReader(jsonText)); + JsonObject actJsonObject = (JsonObject) reader.read(); + + // Do comparison + System.out.println("Compare expJsonObject and actJsonObject for equality"); + pass = JSONP_Util.assertEqualsJsonObjects(expJsonObject, actJsonObject); + + } catch (Exception e) { + throw new Fault("jsonGeneratorObjectTest3 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorObjectTest3 Failed"); + } + + /* + * @testName: jsonGeneratorObjectTest4 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:416; + * JSONP:JAVADOC:289; JSONP:JAVADOC:163; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonObject. + * Encoding is done in UTF-16BE. The output is written to an OutputStream as + * UTF-16BE encoding, read back as a string using UTF-16BE encoding and + * filtered to remove whitespace and is compared against an expected string. + * + * { "object":{"string":"string","number":1,"true":true,"false":false,"null": + * null}, "array":["string", 1, true, false, null] } Tests the following API + * call: + * + * JsonGenerator generator = + * Json.createGeneratorFactory(Map<String,?>).createGenerator(OutputStream, + * Charset); + */ + @Test + public void jsonGeneratorObjectTest4() throws Fault { + boolean pass = true; + try { + System.out.println("Create generator output in UTF-16BE encoding."); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()) + .createGenerator(baos, JSONP_Util.UTF_16BE); + generateSimpleJsonObject(generator); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "{\"object\":{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},\"array\":[\"string\",1,true,false,null]}"; + System.out.println( + "Read the JSON text back encoding from OutputStream using UTF-16BE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-16BE")); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorObjectTest4 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorObjectTest4 Failed"); + } + + /* + * @testName: jsonGeneratorObjectTest5 + * + * @assertion_ids: JSONP:JAVADOC:131; JSONP:JAVADOC:341; JSONP:JAVADOC:295; + * JSONP:JAVADOC:289; + * + * @test_Strategy: Test generation of object data with multiple unicode chars + * in data. The output is written to a writer, read back using a reader as a + * JsonObject and extracts the JsonString value out and compares it against + * the expected JsonString value. + * + * Generate the following object of unicode char(s): + * + * {"unicodechars":"\u0000\u000f\u001f\u00ff\uff00\uffff"} + */ + @Test + public void jsonGeneratorObjectTest5() throws Fault { + boolean pass = true; + JsonReader reader = null; + String expUnicodeChars = "\u0000\u000f\u001f\u00ff\uff00\uffff"; + try { + + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject() + .write("unicodechars", "\u0000\u000f\u001f\u00ff\uff00\uffff") + .writeEnd(); + generator.close(); + sWriter.close(); + + System.out.println("Testing read of " + sWriter.toString()); + reader = Json.createReader(new StringReader(sWriter.toString())); + JsonObject jsonObject = reader.readObject(); + String actUnicodeChars = jsonObject.getJsonString("unicodechars") + .getString(); + reader.close(); + System.out.println("actUnicodeChars=" + actUnicodeChars); + + pass = JSONP_Util.assertEquals(expUnicodeChars, actUnicodeChars); + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + pass = false; + } + if (!pass) + throw new Fault("jsonGeneratorObjectTest5 Failed"); + } + + /* + * @testName: jsonGeneratorArrayTest1 + * + * @assertion_ids: JSONP:JAVADOC:339; JSONP:JAVADOC:341; JSONP:JAVADOC:295; + * JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; JSONP:JAVADOC:325; + * JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:131; JSONP:JAVADOC:289; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonArray. + * The output is written to a writer, read back as a string and filtered to + * remove whitespace and is compared against an expected string. + * + * [ {"string":"string","number":1,"true":true,"false":false,"null":null}, + * ["string", 1, true, false, null] ] + * + */ + @Test + public void jsonGeneratorArrayTest1() throws Fault { + boolean pass = true; + try { + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generateSimpleJsonArray(generator); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "[{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},[\"string\",1,true,false,null]]"; + System.out.println("Read the JSON text back from Writer removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(sWriter.toString()); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorArrayTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorArrayTest1 Failed"); + } + + /* + * @testName: jsonGeneratorArrayTest2 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:168; + * JSONP:JAVADOC:289; JSONP:JAVADOC:327; JSONP:JAVADOC:339; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonArray. + * The output is written to a writer, read back as a string and filtered to + * remove whitespace and is compared against an expected string. + * + * [ "", [], {}, "string", Integer.MIN_VALUE, Integer.MAX_VALUE, + * Long.MIN_VALUE, Long.MAX_VALUE, true, false, null, { "emptyString":"", + * "emptyArray":[], "emptyObject":{}, "string":"string", "number":100, + * "true":true, "false":false, "null":null, "object":{"name":"value"}, + * "array":["one","two"] }, [ "string", Integer.MAX_VALUE, Long.MAX_VALUE, + * true, false, null, {"name":"value"}, ["one","two"] ], + * "\"\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" + * ] + */ + @Test + public void jsonGeneratorArrayTest2() throws Fault { + boolean pass = true; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json.createGenerator(baos); + generator.writeStartArray().write("").writeStartArray().writeEnd() + .writeStartObject().writeEnd().write("string") + .write(Integer.MIN_VALUE).write(Integer.MAX_VALUE) + .write(Long.MIN_VALUE).write(Long.MAX_VALUE).write(JsonValue.TRUE) + .write(JsonValue.FALSE).write(JsonValue.NULL).writeStartObject() + .write("emptyString", "").writeStartArray("emptyArray").writeEnd() + .writeStartObject("emptyObject").writeEnd().write("string", "string") + .write("number", 100).write("true", JsonValue.TRUE) + .write("false", JsonValue.FALSE).write("null", JsonValue.NULL) + .writeStartObject("object").write("name", "value").writeEnd() + .writeStartArray("array").write("one").write("two").writeEnd() + .writeEnd().writeStartArray().write("string").write(Integer.MAX_VALUE) + .write(Long.MAX_VALUE).write(JsonValue.TRUE).write(JsonValue.FALSE) + .write(JsonValue.NULL).writeStartObject().write("name", "value") + .writeEnd().writeStartArray().write("one").write("two").writeEnd() + .writeEnd() + .write( + "\\\"\\\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") + .writeEnd(); + generator.close(); + + System.out.println("Dump of string: " + baos.toString("UTF-8")); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "[\"\",[],{},\"string\"," + Integer.MIN_VALUE + "," + + Integer.MAX_VALUE + "," + Long.MIN_VALUE + "," + Long.MAX_VALUE + + "," + "true,false,null,{\"emptyString\":\"\",\"emptyArray\":[]," + + "\"emptyObject\":{},\"string\":\"string\",\"number\":100,\"true\":true,\"false\":false," + + "\"null\":null,\"object\":{\"name\":\"value\"}," + + "\"array\":[\"one\",\"two\"]},[\"string\"," + Integer.MAX_VALUE + + "," + Long.MAX_VALUE + ",true,false,null," + + "{\"name\":\"value\"},[\"one\",\"two\"]]," + + "\"\\\\\\\"\\\\\\\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM\"" + + "]"; + + System.out.println("Read the JSON text back from Writer removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-8")); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorArrayTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorArrayTest2 Failed"); + } + + /* + * @testName: jsonGeneratorArrayTest3 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:131; + * JSONP:JAVADOC:289; JSONP:JAVADOC:327; JSONP:JAVADOC:339; JSONP:JAVADOC:329; + * JSONP:JAVADOC:321; JSONP:JAVADOC:323; JSONP:JAVADOC:332; JSONP:JAVADOC:337; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonArray. + * The output is written to a writer, read back as a JsonArray and compared + * against an expected JsonArray. + * + * [ "", [], {}, "string", Integer.MIN_VALUE, Integer.MAX_VALUE, + * Long.MIN_VALUE, Long.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE, + * Integer.MAX_VALUE, Integer.MIN_VALUE, true, false, null, { + * "emptyString":"", "emptyArray":[], "emptyObject":{}, "string":"string", + * "number":100, "true":true, "false":false, "null":null, + * "object":{"name":"value",{"foo":"bar"}}, + * "array":["one","two",["foo","bar"]] }, [ "string", Integer.MAX_VALUE, + * Long.MAX_VALUE, Double.MAX_VALUE, Integer.MAX_VALUE true, false, null, + * {"name":"value"}, ["one","two"] ], + * "\"\\!@#$%^&*()_+|~1234567890-=`[]{}:;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" + * ] + */ + @Test + public void jsonGeneratorArrayTest3() throws Fault { + boolean pass = true; + try { + JsonArray expJsonArray = buildJsonArray(); + String jsonText = generateJsonArray(); + System.out.println("generator json text: " + jsonText); + + JsonReader reader = Json.createReader(new StringReader(jsonText)); + JsonArray actJsonArray = (JsonArray) reader.read(); + + // Do comparison + System.out.println("Compare expJsonArray and actJsonArray for equality"); + pass = JSONP_Util.assertEqualsJsonArrays(expJsonArray, actJsonArray); + + } catch (Exception e) { + throw new Fault("jsonGeneratorArrayTest3 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorArrayTest3 Failed"); + } + + /* + * @testName: jsonGeneratorArrayTest4 + * + * @assertion_ids: JSONP:JAVADOC:339; JSONP:JAVADOC:341; JSONP:JAVADOC:115; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:163; JSONP:JAVADOC:289; + * JSONP:JAVADOC:416; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonArray. + * Encoding is done in UTF-16BE. The output is written to an OutputStream as + * UTF-16BE encoding, read back as a string using UTF-16BE encoding and + * filtered to remove whitespace and is compared against an expected string. + * + * [ {"string":"string","number":1,"true":true,"false":false,"null":null}, + * ["string", 1, true, false, null] ] + * + */ + @Test + public void jsonGeneratorArrayTest4() throws Fault { + boolean pass = true; + try { + System.out.println("Create generator output in UTF-16BE encoding."); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()) + .createGenerator(baos, JSONP_Util.UTF_16BE); + generateSimpleJsonArray(generator); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "[{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},[\"string\",1,true,false,null]]"; + System.out.println( + "Read the JSON text back from OutputStream using UTF-16BE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-16BE")); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorArrayTest4 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorArrayTest4 Failed"); + } + + /* + * @testName: jsonGeneratorArrayTest5 + * + * @assertion_ids: JSONP:JAVADOC:131; JSONP:JAVADOC:339; JSONP:JAVADOC:319; + * JSONP:JAVADOC:289; + * + * @test_Strategy: Test generation of array data with multiple unicode chars + * in data. The output is written to a writer, read back using a reader as a + * JsonArray and extracts the JsonString value out and compares it against the + * expected JsonString value. + * + * Generate the following array of unicode char(s): + * + * ["\u0000\u000f\u001f\u00ff\uff00\uffff"] + */ + @Test + public void jsonGeneratorArrayTest5() throws Fault { + boolean pass = true; + JsonReader reader = null; + String expUnicodeChars = "\u0000\u000f\u001f\u00ff\uff00\uffff"; + try { + + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("\u0000\u000f\u001f\u00ff\uff00\uffff") + .writeEnd(); + generator.close(); + sWriter.close(); + + System.out.println("Testing read of " + sWriter.toString()); + reader = Json.createReader(new StringReader(sWriter.toString())); + JsonArray jsonArray = reader.readArray(); + String actUnicodeChars = jsonArray.getJsonString(0).getString(); + reader.close(); + System.out.println("actUnicodeChars=" + actUnicodeChars); + + pass = JSONP_Util.assertEquals(expUnicodeChars, actUnicodeChars); + } catch (Exception e) { + System.err.println("Exception occurred: " + e); + pass = false; + } + if (!pass) + throw new Fault("jsonGeneratorArrayTest5 Failed"); + } + + /* + * @testName: jsonGeneratorObjectConfigTest1 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:289; + * JSONP:JAVADOC:162; JSONP:JAVADOC:416; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonObject. + * This test uses the configuration feature to PRETTY PRINT. The output is + * written to a Writer, read back as a string and filtered to remove + * whitespace and is compared against an expected string. + * + * { "object":{"string":"string","number":1,"true":true,"false":false,"null": + * null}, "array":["string", 1, true, false, null] } Tests following API call: + * + * JsonGenerator generator = Json.createGeneratorFactory(Map<String, + * ?>).createGenerator(Writer) + */ + @Test + public void jsonGeneratorObjectConfigTest1() throws Fault { + boolean pass = true; + try { + System.out.println("Create JsonGenerator using configuration with PRETTY_PRINTING"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getPrettyPrintingConfig()) + .createGenerator(sWriter); + generateSimpleJsonObject(generator); + + // Dump JsonText output with PRETTY_PRINTING feature + System.out.println("PRETTY_PRINTING feature\n" + sWriter.toString()); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "{\"object\":{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},\"array\":[\"string\",1,true,false,null]}"; + System.out.println("Read the JSON text back from Writer removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(sWriter.toString()); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorObjectConfigTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorObjectConfigTest1 Failed"); + } + + /* + * @testName: jsonGeneratorObjectConfigTest2 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:289; + * JSONP:JAVADOC:200; JSONP:JAVADOC:416; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonObject. + * This test uses the configuration feature to PRETTY PRINT. The output is + * written to a OutputStream, read back as a string and filtered to remove + * whitespace and is compared against an expected string. + * + * { "object":{"string":"string","number":1,"true":true,"false":false,"null": + * null}, "array":["string", 1, true, false, null] } Tests following API call: + * + * JsonGenerator generator = Json.createGeneratorFactory(Map<String, + * ?>).createGenerator(OutputStream) + */ + @Test + public void jsonGeneratorObjectConfigTest2() throws Fault { + boolean pass = true; + try { + System.out.println("Create JsonGenerator using configuration with PRETTY_PRINTING"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getPrettyPrintingConfig()) + .createGenerator(baos); + generateSimpleJsonObject(generator); + + // Dump JsonText output with PRETTY_PRINTING feature + System.out.println("PRETTY_PRINTING feature\n" + baos.toString("UTF-8")); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "{\"object\":{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},\"array\":[\"string\",1,true,false,null]}"; + System.out.println("Read the JSON text back from Writer removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-8")); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorObjectConfigTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorObjectConfigTest2 Failed"); + } + + /* + * @testName: jsonGeneratorObjectEncodingTest1 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:163; + * JSONP:JAVADOC:289; JSONP:JAVADOC:416; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonObject. + * The output is written to an OutputStream using UTF-8 encoding, read back as + * a string and filtered to remove whitespace and is compared against an + * expected string. + * + * { "object":{"string":"string","number":1,"true":true,"false":false,"null": + * null}, "array":["string", 1, true, false, null] } + */ + @Test + public void jsonGeneratorObjectEncodingTest1() throws Fault { + boolean pass = true; + try { + System.out.println("Create JsonGenerator using UTF-8 encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()) + .createGenerator(baos, JSONP_Util.UTF_8); + generateSimpleJsonObject(generator); + + // Dump JsonText output + System.out.println("Generator Output=" + baos.toString("UTF-8")); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "{\"object\":{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},\"array\":[\"string\",1,true,false,null]}"; + System.out.println( + "Read the JSON text back from OutputStream using UTF-8 encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-8")); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorObjectEncodingTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorObjectEncodingTest1 Failed"); + } + + /* + * @testName: jsonGeneratorObjectEncodingTest2 + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:289; + * JSONP:JAVADOC:163; JSONP:JAVADOC:416; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonObject. + * This test uses the configuration feature to PRETTY PRINT. The output is + * written to an OutputStream using UTF-16BE encoding, read back as a string + * and filtered to remove whitespace and is compared against an expected + * string. + * + * { "object":{"string":"string","number":1,"true":true,"false":false,"null": + * null}, "array":["string", 1, true, false, null] } Tests the following API + * call: + * + * JsonGenerator generator = Json.createGeneratorFactory(Map<String, + * ?>).createGenerator(OutputStream, Charset); + */ + @Test + public void jsonGeneratorObjectEncodingTest2() throws Fault { + boolean pass = true; + try { + System.out.println( + "Create JsonGenerator using configuration with PRETTY_PRINTING using UTF-16BE encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getPrettyPrintingConfig()) + .createGenerator(baos, JSONP_Util.UTF_16BE); + generateSimpleJsonObject(generator); + + // Dump JsonText output with PRETTY_PRINTING feature + System.out.println("PRETTY_PRINTING feature\n" + baos.toString("UTF-16BE")); + + // Do comparison + System.out.println("Create expected JSON text with no whitespace"); + String expJson = "{\"object\":{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},\"array\":[\"string\",1,true,false,null]}"; + System.out.println( + "Read the JSON text back from OutputStream using UTF-16BE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-16BE")); + pass = JSONP_Util.assertEqualsJsonText(expJson, actJson); + + } catch (Exception e) { + throw new Fault("jsonGeneratorObjectEncodingTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonGeneratorObjectEncodingTest2 Failed"); + } + + /* + * @testName: jsonGeneratorUTFEncodedTests + * + * @assertion_ids: JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * JSONP:JAVADOC:295; JSONP:JAVADOC:304; JSONP:JAVADOC:292; JSONP:JAVADOC:317; + * JSONP:JAVADOC:325; JSONP:JAVADOC:319; JSONP:JAVADOC:115; JSONP:JAVADOC:163; + * JSONP:JAVADOC:289; JSONP:JAVADOC:416; + * + * @test_Strategy: Tests various JsonGenerator API's to create a JsonObject. + * + * The output is written to an OutputStream using all supported UTF encodings + * and read back as a string and filtered to remove whitespace and is compared + * against an expected string. The following UTF encodings are tested: + * + * UTF8 UTF16 UTF16LE UTF16BE UTF32LE UTF32BE + * + * { "object":{"string":"string","number":1,"true":true,"false":false,"null": + * null}, "array":["string", 1, true, false, null] } + */ + @Test + public void jsonGeneratorUTFEncodedTests() throws Fault { + boolean pass = true; + System.out.println( + "Create expected JSON text with no whitespace for use with comparison"); + String expJson = "{\"object\":{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},\"array\":[\"string\",1,true,false,null]}"; + try { + System.out.println( + "-----------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createGeneratorFactory(Map<String,?>).createGenerator(OutputStream, Charset) as UTF-8]"); + System.out.println( + "-----------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonGenerator using UTF-8 encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()) + .createGenerator(baos, JSONP_Util.UTF_8); + generateSimpleJsonObject(generator); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-8")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-8 encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-8")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing generation to UTF-8 encoding: " + e); + } + try { + System.out.println( + "------------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createGeneratorFactory(Map<String,?>).createGenerator(OutputStream, Charset) as UTF-16]"); + System.out.println( + "------------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonGenerator using UTF-16 encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()) + .createGenerator(baos, JSONP_Util.UTF_16); + generateSimpleJsonObject(generator); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-16")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-16 encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-16")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing generation to UTF-16 encoding: " + e); + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createGeneratorFactory(Map<String,?>).createGenerator(OutputStream, Charset) as UTF-16LE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonGenerator using UTF-16LE encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()) + .createGenerator(baos, JSONP_Util.UTF_16LE); + generateSimpleJsonObject(generator); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-16LE")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-16LE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-16LE")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println( + "Exception occurred testing generation to UTF-16LE encoding: " + e); + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createGeneratorFactory(Map<String,?>).createGenerator(OutputStream, Charset) as UTF-16BE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonGenerator using UTF-16BE encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()) + .createGenerator(baos, JSONP_Util.UTF_16BE); + generateSimpleJsonObject(generator); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-16BE")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-16BE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-16BE")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println( + "Exception occurred testing generation to UTF-16BE encoding: " + e); + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createGeneratorFactory(Map<String,?>).createGenerator(OutputStream, Charset) as UTF-32LE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonGenerator using UTF-32LE encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()) + .createGenerator(baos, JSONP_Util.UTF_32LE); + generateSimpleJsonObject(generator); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-32LE")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-32LE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-32LE")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println( + "Exception occurred testing generation to UTF-32LE encoding: " + e); + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createGeneratorFactory(Map<String,?>).createGenerator(OutputStream, Charset) as UTF-32BE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonGenerator using UTF-32BE encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json + .createGeneratorFactory(JSONP_Util.getEmptyConfig()) + .createGenerator(baos, JSONP_Util.UTF_32BE); + generateSimpleJsonObject(generator); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-32BE")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-32BE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-32BE")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println( + "Exception occurred testing generation to UTF-32BE encoding: " + e); + } + if (!pass) + throw new Fault("jsonGeneratorUTFEncodedTests Failed"); + } + + /* + * @testName: jsonGeneratorExceptionTests + * + * @assertion_ids: JSONP:JAVADOC:339; JSONP:JAVADOC:341; JSONP:JAVADOC:115; + * JSONP:JAVADOC:293; JSONP:JAVADOC:296; JSONP:JAVADOC:299; JSONP:JAVADOC:302; + * JSONP:JAVADOC:305; JSONP:JAVADOC:308; JSONP:JAVADOC:311; JSONP:JAVADOC:315; + * JSONP:JAVADOC:297; JSONP:JAVADOC:303; JSONP:JAVADOC:306; JSONP:JAVADOC:309; + * JSONP:JAVADOC:312; JSONP:JAVADOC:316; JSONP:JAVADOC:336; JSONP:JAVADOC:335; + * JSONP:JAVADOC:290; JSONP:JAVADOC:331; JSONP:JAVADOC:381; JSONP:JAVADOC:382; + * JSONP:JAVADOC:350; JSONP:JAVADOC:352; JSONP:JAVADOC:354; JSONP:JAVADOC:356; + * JSONP:JAVADOC:358; JSONP:JAVADOC:360; JSONP:JAVADOC:362; JSONP:JAVADOC:364; + * JSONP:JAVADOC:366; JSONP:JAVADOC:347; JSONP:JAVADOC:348; JSONP:JAVADOC:368; + * JSONP:JAVADOC:370; JSONP:JAVADOC:372; JSONP:JAVADOC:374; + * + * @test_Strategy: Tests various exception test cases. + * + * NumberFormatException JsonGenerationException + * + */ + @Test + public void jsonGeneratorExceptionTests() throws Fault { + boolean pass = true; + + // Test NumberFormatException for write(double) if value is + // Not-a-Number(NaN) or infinity + try { + System.out.println( + "Trip NumberFormatException for write(double) if value is Not-a-Number(NaN) or infinity"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write(Double.NaN); + System.err.println("Did not get expected NumberFormatException"); + pass = false; + } catch (NumberFormatException e) { + System.out.println("Caught expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test NumberFormatException for write(double) if value is + // Not-a-Number(NaN) or infinity + try { + System.out.println( + "Trip NumberFormatException for write(double) if value is Not-a-Number(NaN) or infinity"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write(Double.NEGATIVE_INFINITY); + System.err.println("Did not get expected NumberFormatException"); + pass = false; + } catch (NumberFormatException e) { + System.out.println("Caught expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test NumberFormatException for write(double) if value is + // Not-a-Number(NaN) or infinity + try { + System.out.println( + "Trip NumberFormatException for write(double) if value is Not-a-Number(NaN) or infinity"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write(Double.POSITIVE_INFINITY); + System.err.println("Did not get expected NumberFormatException"); + pass = false; + } catch (NumberFormatException e) { + System.out.println("Caught expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test NumberFormatException for write(String,double) if value is + // Not-a-Number(NaN) or infinity + try { + System.out.println( + "Trip NumberFormatException for write(String,double) if value is Not-a-Number(NaN) or infinity"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write("badnumber", Double.NaN); + System.err.println("Did not get expected NumberFormatException"); + pass = false; + } catch (NumberFormatException e) { + System.out.println("Caught expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test NumberFormatException for write(String,double) if value is + // Not-a-Number(NaN) or infinity + try { + System.out.println( + "Trip NumberFormatException for write(String,double) if value is Not-a-Number(NaN) or infinity"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write("badnumber", Double.NEGATIVE_INFINITY); + System.err.println("Did not get expected NumberFormatException"); + pass = false; + } catch (NumberFormatException e) { + System.out.println("Caught expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test NumberFormatException for write(String,double) if value is + // Not-a-Number(NaN) or infinity + try { + System.out.println( + "Trip NumberFormatException for write(String,double) if value is Not-a-Number(NaN) or infinity"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write("badnumber", Double.POSITIVE_INFINITY); + System.err.println("Did not get expected NumberFormatException"); + pass = false; + } catch (NumberFormatException e) { + System.out.println("Caught expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonGenerationExceptipn if an incomplete JSON is generated. + try { + System.out.println( + "Trip JsonGenerationExceptipn if an incomplete JSON is generated."); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write("name", "value"); + generator.close(); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonGenerationExceptipn if an incomplete JSON is generated. + try { + System.out.println( + "Trip JsonGenerationExceptipn if an incomplete JSON is generated."); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("string"); + generator.close(); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(JsonValue) if not called within + // array context + try { + System.out.println( + "Trip JsonGenerationException for write(JsonValue) if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write(JsonValue.TRUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String) if not called within array + // context + try { + System.out.println( + "Trip JsonGenerationException for write(String) if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write("name"); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(BigInteger) if not called within + // array context + try { + System.out.println( + "Trip JsonGenerationException for write(BigInteger) if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject() + .write(new BigInteger(new Integer(Integer.MAX_VALUE).toString())); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(BigDecimal) if not called within + // array context + try { + System.out.println( + "Trip JsonGenerationException for write(BigDecimal) if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write(BigDecimal.valueOf(Integer.MIN_VALUE)); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(int) if not called within array + // context + try { + System.out.println( + "Trip JsonGenerationException for write(int) if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write(Integer.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(long) if not called within array + // context + try { + System.out.println( + "Trip JsonGenerationException for write(long) if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write(Long.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(double) if not called within array + // context + try { + System.out.println( + "Trip JsonGenerationException for write(double) if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write(Double.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(boolean) if not called within + // array context + try { + System.out.println( + "Trip JsonGenerationException for write(boolean) if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write(true); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for writeNull() if not called within array + // context + try { + System.out.println( + "Trip JsonGenerationException for writeNull() if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeNull(); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for writeStartArray() if not called within + // array context + try { + System.out.println( + "Trip JsonGenerationException for writeStartArray() if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeStartArray(); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for writeStartObject() if not called within + // array context + try { + System.out.println( + "Trip JsonGenerationException for writeStartObject() if not called within array context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeStartObject(); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,JsonValue) if not called + // within object context + try { + System.out.println( + "Trip JsonGenerationException for write(String,JsonValue) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("string", JsonValue.TRUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,String) if not called + // within object context + try { + System.out.println( + "Trip JsonGenerationException for write(String,String) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("string", "name"); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,BigInteger) if not called + // within object context + try { + System.out.println( + "Trip JsonGenerationException for write(String,BigInteger) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("string", + new BigInteger(new Integer(Integer.MAX_VALUE).toString())); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,BigDecimal) if not called + // within object context + try { + System.out.println( + "Trip JsonGenerationException for write(String,BigDecimal) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("string", + BigDecimal.valueOf(Integer.MIN_VALUE)); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,int) if not called within + // object context + try { + System.out.println( + "Trip JsonGenerationException for write(String,int) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("string", Integer.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,long) if not called within + // object context + try { + System.out.println( + "Trip JsonGenerationException for write(String,long) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("string", Long.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,double) if not called + // within object context + try { + System.out.println( + "Trip JsonGenerationException for write(String,double) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("string", Double.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,boolean) if not called + // within object context + try { + System.out.println( + "Trip JsonGenerationException for write(String,boolean) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write("string", true); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for writeNull(String) if not called within + // object context + try { + System.out.println( + "Trip JsonGenerationException for writeNull(String) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeNull("string"); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for writeStartArray(String) if not called + // within object context + try { + System.out.println( + "Trip JsonGenerationException for writeStartArray(String) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeStartArray("string"); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for writeStartObject(String) if not called + // within object context + try { + System.out.println( + "Trip JsonGenerationException for writeStartObject(String) if not called within object context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeStartObject("string"); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,JsonValue) when invoked + // after the writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(String,JsonValue) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeEnd().write("name", "value"); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for writeEnd() when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for writeEnd() when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeEnd().writeEnd(); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,BigInteger) when invoked + // after the writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(String,BigInteger) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeEnd().write("name", + new BigInteger(new Integer(Integer.MAX_VALUE).toString())); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,BigDecimal) when invoked + // after the writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(String,BigDecimal) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeEnd().write("name", + BigDecimal.valueOf(Integer.MIN_VALUE)); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,int) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(String,int) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeEnd().write("name", Integer.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,long) when invoked after + // the writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(String,long) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeEnd().write("name", Long.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,double) when invoked after + // the writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(String,double) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeEnd().write("name", Double.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String,boolean) when invoked after + // the writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(String,boolean) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeEnd().write("name", false); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for writeNull(String) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for writeNull(String) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeEnd().writeNull("name"); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(JsonValue) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(JsonValue) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeEnd().write(JsonValue.TRUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(String) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(String) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeEnd().write(JsonValue.TRUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(BigDecimal) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(BigDecimal) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeEnd() + .write(BigDecimal.valueOf(Integer.MIN_VALUE)); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(BigInteger) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(BigInteger) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeEnd() + .write(new BigInteger(new Integer(Integer.MAX_VALUE).toString())); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(int) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(int) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeEnd().write(Integer.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(long) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(long) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeEnd().write(Long.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(double) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(double) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeEnd().write(Double.MAX_VALUE); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for write(boolean) when invoked after the + // writeEnd method is called + try { + System.out.println( + "Trip JsonGenerationException for write(boolean) when invoked after the writeEnd method is called"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeEnd().write(true); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test JsonGenerationException for for writeNull() when invoked with no + // context + try { + System.out.println( + "Trip JsonGenerationException for for writeNull() when invoked with no context"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().writeEnd().writeNull(); + System.err.println("Did not get expected JsonGenerationException"); + pass = false; + } catch (JsonGenerationException e) { + System.out.println("Caught expected JsonGenerationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonGeneratorExceptionTests Failed"); + } + + /* + * @testName: flushTest + * + * @assertion_ids: JSONP:JAVADOC:131; JSONP:JAVADOC:289; JSONP:JAVADOC:291; + * JSONP:JAVADOC:340; JSONP:JAVADOC:341; JSONP:JAVADOC:342; + * + * @test_Strategy: Generate some partial Json, flush output and compare + * output. Generate additional Json to complete, flush output again and + * compare. Test passes if comparisons are correct. + * + * {"object":{},"array":[]} + */ + @Test + public void flushTest() throws Fault { + boolean pass = true; + try { + System.out.println("Generate some partial Json and flush output."); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().writeStartObject("object").writeEnd() + .flush(); + + // Do comparison 1 + System.out.println("Create expected partial JSON text with no whitespace"); + String expJson = "{\"object\":{}"; + System.out.println("Read the JSON text back from Writer removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(sWriter.toString()); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + System.out.println("Generate additional Json to complete and flush output."); + generator.writeStartArray("array").writeEnd().writeEnd().flush(); + + // Do comparison 2 + expJson = "{\"object\":{},\"array\":[]}"; + System.out.println("Read the JSON text back from Writer removing whitespace"); + actJson = JSONP_Util.removeWhitespace(sWriter.toString()); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + generator.close(); + + } catch (Exception e) { + throw new Fault("flushTest Failed: ", e); + } + if (!pass) + throw new Fault("flushTest Failed"); + } + + /* + * @testName: jsonGeneratorIOErrorTests + * + * @assertion_ids: JSONP:JAVADOC:346; JSONP:JAVADOC:551; + * + * @test_Strategy: Tests for JsonException for testable i/o errors. + * + */ + @Test + public void jsonGeneratorIOErrorTests() throws Fault { + boolean pass = true; + + // Trip JsonException if there is an i/o error on JsonGenerator.close() + try { + System.out.println( + "Trip JsonException if there is an i/o error on JsonGenerator.close()."); + MyBufferedWriter mbw = new MyBufferedWriter(new StringWriter()); + JsonGenerator generator = Json.createGenerator(mbw); + generator.writeStartObject().writeEnd(); + mbw.setThrowIOException(true); + System.out.println("Calling JsonGenerator.close()"); + generator.close(); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonException if there is an i/o error on JsonGenerator.flush() + try { + System.out.println( + "Trip JsonException if there is an i/o error on JsonGenerator.flush()."); + MyBufferedWriter mbw = new MyBufferedWriter(new StringWriter()); + JsonGenerator generator = Json.createGenerator(mbw); + generator.writeStartObject().writeEnd(); + mbw.setThrowIOException(true); + System.out.println("Calling JsonGenerator.flush()"); + generator.flush(); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonGeneratorIOErrorTests Failed"); + } + + /* + * @testName: jsonGeneratorDocumentRootTest + * + * @assertion_ids: JSONP:JAVADOC:317; JSONP:JAVADOC:319; JSONP:JAVADOC:321; + * JSONP:JAVADOC:323; JSONP:JAVADOC:325; JSONP:JAVADOC:327; JSONP:JAVADOC:329; + * JSONP:JAVADOC:332; JSONP:JAVADOC:583; JSONP:JAVADOC:584; JSONP:JAVADOC:585; + * JSONP:JAVADOC:586; JSONP:JAVADOC:587; JSONP:JAVADOC:588; JSONP:JAVADOC:662; + * JSONP:JAVADOC:663; JSONP:JAVADOC:664; JSONP:JAVADOC:665; JSONP:JAVADOC:666; + * JSONP:JAVADOC:667; JSONP:JAVADOC:289; JSONP:JAVADOC:341; JSONP:JAVADOC:672; + * + * @test_Strategy: Tests RFC 7159 grammar changes:<br> {@code + * "JSON-text = ws value ws"}<br> {@code + * "value = false / null / true / object / array / number / string"} + */ + @Test + public void jsonGeneratorDocumentRootTest() throws Fault { + Generator genTest = new Generator(); + final TestResult result = genTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsongeneratortests/Generator.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsongeneratortests/Generator.java new file mode 100644 index 0000000..0064716 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsongeneratortests/Generator.java
@@ -0,0 +1,220 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsongeneratortests; + +import jakarta.jsonp.tck.api.common.JsonValueType; +import jakarta.jsonp.tck.api.common.TestResult; +import java.io.StringReader; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.BigInteger; +import jakarta.json.Json; +import jakarta.json.JsonReader; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonGenerator; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; +import jakarta.json.JsonObject; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests: {@link JsonGenerator} + * API methods. + */ +public class Generator { + + /** Tests input data. */ + private static final Object[] VALUES = new Object[] { OBJ_VALUE, // write(JsonValue) + // for + // JsonObject + createEmptyArrayWithStr(), // write(JsonValue) for simple JsonArray + STR_VALUE, // write(JsonValue) for String + INT_VALUE, // write(JsonValue) for int + LNG_VALUE, // write(JsonValue) for long + DBL_VALUE, // write(JsonValue) for double + BIN_VALUE, // write(JsonValue) for BigInteger + BDC_VALUE, // write(JsonValue) for BigDecimal + BOOL_VALUE, // write(JsonValue) for boolean + null // write(JsonValue) for null + }; + + /** + * Test {@link JsonGenerator} API methods. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonGenerator API methods for RFC 7159 grammar changes."); + System.out.println("JsonGenerator API methods for RFC 7159 grammar changes."); + testPrimitiveTypesInRoot(result); + testWrittingObjectByParts(result); + return result; + } + + /** + * Test primitive types as JSON value stored in JSON document root. RFC 7159 + * grammar changes now allows such a values to be stored in JSON document + * root. + */ + private void testPrimitiveTypesInRoot(final TestResult result) { + for (Object value : VALUES) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println(" - write(JsonValue) for " + typeName + " as an argument"); + verifyJsonGeneratorForJsonValue(result, value); + verifyJsonGeneratorForSimpleType(result, value); + } + } + + /** + * Verify JSON object generation using low level methods + * {@code writeStartObject()}, {@code writeEnd()}, {@code writeKey(String)} + * and {@code write(String)}. + */ + private void testWrittingObjectByParts(final TestResult result) { + System.out.println(" - generate JSON object"); + final StringWriter strWriter = new StringWriter(); + try (JsonGenerator generator = Json.createGenerator(strWriter)) { + generator.writeStartObject(); + generator.writeKey(STR_NAME); + generator.write(STR_VALUE); + generator.writeEnd(); + } + final String out = strWriter.toString(); + final JsonObject check = createSimpleObjectStr(); + if (operationFailed(check, out)) { + final String checkStr = check.toString(); + System.out.println( + " Generated JSON object " + out + " shall be " + checkStr); + result.fail("generate JSON object", + "Generated value " + out + " shall be " + checkStr); + } else { + System.out.println(" Output: " + out); + } + + } + + /** + * Verify JSON document root generation for provided JSON value. + */ + private void verifyJsonGeneratorForJsonValue(final TestResult result, + final Object value) { + final StringWriter strWriter = new StringWriter(); + final JsonValue jsonValue = toJsonValue(value); + try (JsonGenerator generator = Json.createGenerator(strWriter)) { + generator.write(jsonValue); + } + final String out = strWriter.toString(); + if (operationFailed(jsonValue, out)) { + final String check = jsonValue.toString(); + System.out.println(" Generated JSON value " + out + " shall be " + check); + result.fail("write(JsonValue)", + "Generated value " + out + " shall be " + check); + } else { + System.out.println(" Output (JsonValue): " + out); + } + } + + /** + * Verify JSON document root generation for provided JSON value. + */ + @SuppressWarnings("UnnecessaryUnboxing") + private void verifyJsonGeneratorForSimpleType(final TestResult result, + final Object value) { + final StringWriter strWriter = new StringWriter(); + try (JsonGenerator generator = Json.createGenerator(strWriter)) { + switch (JsonValueType.getType(value)) { + case String: + generator.write((String) value); + break; + case Integer: + generator.write(((Integer) value).intValue()); + break; + case Long: + generator.write(((Long) value).longValue()); + break; + case BigInteger: + generator.write((BigInteger) value); + break; + case Double: + generator.write(((Double) value).doubleValue()); + break; + case BigDecimal: + generator.write((BigDecimal) value); + break; + case Boolean: + generator.write(((Boolean) value).booleanValue() ? JsonValue.TRUE + : JsonValue.FALSE); + break; + case JsonValue: + generator.write((JsonValue) value); + break; + case Null: + generator.write(JsonValue.NULL); + break; + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + final String out = strWriter.toString(); + if (operationFailed(value, out)) { + final String check = toJsonValue(value).toString(); + System.out.println(" Generated simple value " + out + " shall be " + check); + result.fail("write(JsonValue)", + "Generated value " + out + " shall be " + check); + } else { + System.out.println(" Output (simple): " + out); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final Object check, final String out) { + return out == null || !assertEquals(check, out); + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, final String out) { + if (out == null) { + return true; + } + try (final JsonReader reader = Json.createReader(new StringReader(out))) { + final JsonValue actVal = reader.readValue(); + return !assertEquals((JsonValue) check, actVal); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonnumbertests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonnumbertests/ClientTests.java new file mode 100644 index 0000000..6c79b66 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonnumbertests/ClientTests.java
@@ -0,0 +1,203 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonnumbertests; + +import jakarta.json.*; +import jakarta.json.stream.*; + +import java.io.*; + +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; +import java.math.BigDecimal; +import java.math.BigInteger; + +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonNumberEqualsTest + * + * @assertion_ids: JSONP:JAVADOC:250; + * + * @test_Strategy: Tests JsonNumber equals method. Create 2 equal JsonNumbers + * and compare them for equality and expect true. Create 2 non-equal + * JsonNumbers and compare them for equality and expect false. + */ + @Test + public void jsonNumberEqualsTest() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonNumber 1 for testing"); + JsonNumber number1 = JSONP_Util.createJsonNumber(10); + System.out.println("number1=" + JSONP_Util.toStringJsonNumber(number1)); + + System.out.println("Create sample JsonNumber 2 for testing"); + JsonNumber number2 = JSONP_Util.createJsonNumber(10); + System.out.println("number2=" + JSONP_Util.toStringJsonNumber(number2)); + + System.out.println( + "Call JsonNumber.equals() to compare 2 equal JsonNumbers and expect true"); + if (number1.equals(number2)) { + System.out.println("JsonNumbers are equal - expected."); + } else { + pass = false; + System.err.println("JsonNumbers are not equal - unexpected."); + } + + System.out.println("Create sample JsonNumber 1 for testing"); + number1 = JSONP_Util.createJsonNumber(10); + System.out.println("number1=" + JSONP_Util.toStringJsonNumber(number1)); + + System.out.println("Create sample JsonNumber 2 for testing"); + number2 = JSONP_Util.createJsonNumber((double) 10.25); + System.out.println("number2=" + JSONP_Util.toStringJsonNumber(number2)); + + System.out.println( + "Call JsonNumber.equals() to compare 2 equal JsonNumbers and expect false"); + if (!number1.equals(number2)) { + System.out.println("JsonNumbers are not equal - expected."); + } else { + pass = false; + System.err.println("JsonNumbers are equal - unexpected."); + } + } catch (Exception e) { + throw new Fault("jsonNumberEqualsTest Failed: ", e); + } + if (!pass) + throw new Fault("jsonNumberEqualsTest Failed"); + } + + /* + * @testName: jsonNumberHashCodeTest + * + * @assertion_ids: JSONP:JAVADOC:251; + * + * @test_Strategy: Tests JsonNumber equals method. Create 2 equal JsonNumbers + * and compare them for hashcode and expect true. Create 2 non-equal + * JsonNumbers and compare them for hashcode and expect false. + */ + @Test + public void jsonNumberHashCodeTest() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonNumber 1 for testing"); + JsonNumber number1 = JSONP_Util.createJsonNumber(10); + System.out.println("number1=" + JSONP_Util.toStringJsonNumber(number1)); + System.out.println("number1.hashCode()=" + number1.hashCode()); + + System.out.println("Create sample JsonNumber 2 for testing"); + JsonNumber number2 = JSONP_Util.createJsonNumber(10); + System.out.println("number2=" + JSONP_Util.toStringJsonNumber(number2)); + System.out.println("number2.hashCode()=" + number2.hashCode()); + + System.out.println( + "Call JsonNumber.hashCode() to compare 2 equal JsonNumbers and expect true"); + if (number1.hashCode() == number2.hashCode()) { + System.out.println("JsonNumbers hashCode are equal - expected."); + } else { + pass = false; + System.err.println("JsonNumbers hashCode are not equal - unexpected."); + } + + System.out.println("Create sample JsonNumber 1 for testing"); + number1 = JSONP_Util.createJsonNumber(10); + System.out.println("number1=" + JSONP_Util.toStringJsonNumber(number1)); + System.out.println("number1.hashCode()=" + number1.hashCode()); + + System.out.println("Create sample JsonNumber 2 for testing"); + number2 = JSONP_Util.createJsonNumber((double) 10.25); + System.out.println("number2=" + JSONP_Util.toStringJsonNumber(number2)); + System.out.println("number2.hashCode()=" + number2.hashCode()); + + System.out.println( + "Call JsonNumber.hashCode() to compare 2 equal JsonNumbers and expect false"); + if (number1.hashCode() != number2.hashCode()) { + System.out.println("JsonNumbers hashCode are not equal - expected."); + } else { + pass = false; + System.err.println("JsonNumbers hashCode are equal - unexpected."); + } + } catch (Exception e) { + throw new Fault("jsonNumberHashCodeTest Failed: ", e); + } + if (!pass) + throw new Fault("jsonNumberHashCodeTest Failed"); + } + + /* + * @testName: jsonNumberIsIntegralTest + * + * @assertion_ids: JSONP:JAVADOC:51; + * + * @test_Strategy: Test JsonNumber.isIntegral() method. + */ + @Test + public void jsonNumberIsIntegralTest() throws Fault { + boolean pass = true; + JsonNumber jsonNumber = null; + try { + // INTEGRAL NUMBER TEST + JsonNumber number1 = JSONP_Util.createJsonNumber(123); + if (!JSONP_Util.assertEqualsJsonNumberType(number1.isIntegral(), + JSONP_Util.INTEGRAL)) + pass = false; + else { + if (!JSONP_Util.assertEquals(123, number1.intValue())) + pass = false; + } + // NON_INTEGRAL NUMBER TEST + JsonNumber number2 = JSONP_Util.createJsonNumber(12345.45); + if (!JSONP_Util.assertEqualsJsonNumberType(number2.isIntegral(), + JSONP_Util.NON_INTEGRAL)) + pass = false; + else { + if (!JSONP_Util.assertEquals(12345.45, number2.doubleValue())) + pass = false; + } + + } catch (Exception e) { + throw new Fault("jsonNumberIsIntegralTest Failed: ", e); + } + + if (!pass) + throw new Fault("jsonNumberIsIntegralTest Failed"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonobjecttests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonobjecttests/ClientTests.java new file mode 100644 index 0000000..9ba6ce2 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonobjecttests/ClientTests.java
@@ -0,0 +1,1360 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonobjecttests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.json.*; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonObjectTest1 + * + * @assertion_ids: JSONP:JAVADOC:58; JSONP:JAVADOC:61; JSONP:JAVADOC:64; + * JSONP:JAVADOC:67; JSONP:JAVADOC:70; JSONP:JAVADOC:73; JSONP:JAVADOC:76; + * JSONP:JAVADOC:80; JSONP:JAVADOC:86; JSONP:JAVADOC:400; JSONP:JAVADOC:401; + * JSONP:JAVADOC:402; JSONP:JAVADOC:403; JSONP:JAVADOC:404; JSONP:JAVADOC:406; + * JSONP:JAVADOC:408; JSONP:JAVADOC:409; + * + * @test_Strategy: Tests JsonObject/JsonObjectBuilder API's. Build a + * JsonObject using the JsonObjectBuilder API's then verify that the Map of + * JsonObject values matches the expected Map of JsonObject values. + */ + @Test + public void jsonObjectTest1() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject object = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create sample JsonArray for testing"); + JsonArray array = JSONP_Util.createSampleJsonArray(); + + System.out.println("Create the expected map of JsonObject values"); + Map<String, JsonValue> expMap = new HashMap<>(); + expMap.put("false", JsonValue.FALSE); + expMap.put("true", JsonValue.TRUE); + expMap.put("null", JsonValue.NULL); + expMap.put("doublemin", JSONP_Util.createJsonNumber(Double.MIN_VALUE)); + expMap.put("doublemax", JSONP_Util.createJsonNumber(Double.MAX_VALUE)); + expMap.put("intmin", JSONP_Util.createJsonNumber(Integer.MIN_VALUE)); + expMap.put("intmax", JSONP_Util.createJsonNumber(Integer.MAX_VALUE)); + expMap.put("longmin", JSONP_Util.createJsonNumber(Long.MIN_VALUE)); + expMap.put("longmax", JSONP_Util.createJsonNumber(Long.MAX_VALUE)); + expMap.put("bigdecimal", + JSONP_Util.createJsonNumber(BigDecimal.valueOf(123456789.123456789))); + expMap.put("biginteger", + JSONP_Util.createJsonNumber(new BigInteger("123456789"))); + expMap.put("string", JSONP_Util.createJsonString("string1")); + expMap.put("false2", JsonValue.FALSE); + expMap.put("true2", JsonValue.TRUE); + expMap.put("null2", JsonValue.NULL); + expMap.put("object", object); + expMap.put("array", array); + JSONP_Util.dumpMap(expMap, "Expected Map"); + + System.out.println("Create JsonObject using all JsonObjectBuilder API's"); + JsonObject myJsonObject = Json.createObjectBuilder() + .add("false", JsonValue.FALSE).add("true", JsonValue.TRUE) + .add("null", JsonValue.NULL).add("doublemin", Double.MIN_VALUE) + .add("doublemax", Double.MAX_VALUE).add("intmin", Integer.MIN_VALUE) + .add("intmax", Integer.MAX_VALUE).add("longmin", Long.MIN_VALUE) + .add("longmax", Long.MAX_VALUE) + .add("bigdecimal", BigDecimal.valueOf(123456789.123456789)) + .add("biginteger", new BigInteger("123456789")) + .add("string", "string1").add("false2", false).add("true2", true) + .addNull("null2").add("object", object).add("array", array).build(); + + Map<String, JsonValue> actMap = myJsonObject; + JSONP_Util.dumpMap(actMap, "Actual Map"); + System.out.println( + "Compare actual Map of JsonObject values with expected Map of JsonObject values"); + pass = JSONP_Util.assertEqualsMap(expMap, actMap); + } catch (Exception e) { + throw new Fault("jsonObjectTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonObjectTest1 Failed"); + } + + /* + * @testName: jsonObjectTest2 + * + * @assertion_ids: JSONP:JAVADOC:86; JSONP:JAVADOC:58; JSONP:JAVADOC:61; + * JSONP:JAVADOC:64; JSONP:JAVADOC:67; JSONP:JAVADOC:70; JSONP:JAVADOC:73; + * JSONP:JAVADOC:76; JSONP:JAVADOC:80; JSONP:JAVADOC:185; JSONP:JAVADOC:400; + * JSONP:JAVADOC:401; JSONP:JAVADOC:402; JSONP:JAVADOC:403; JSONP:JAVADOC:404; + * JSONP:JAVADOC:406; JSONP:JAVADOC:408; JSONP:JAVADOC:409; + * + * @test_Strategy: Tests JsonObject/JsonObjectBuilder API's. Build a + * JsonObject using the JsonObjectBuilder API's. Write the JsonObject to a + * JsonWriter and read it back using a JsonReader. Verify that JsonObject + * written to the JsonWriter and then read back using the JsonReader are + * equal. + */ + @Test + public void jsonObjectTest2() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject object = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create sample JsonArray for testing"); + JsonArray array = JSONP_Util.createSampleJsonArray(); + + System.out.println( + "Create JsonObject 'myJsonObject1' using all JsonObjectBuilder API's"); + JsonObject myJsonObject1 = Json.createObjectBuilder() + .add("false", JsonValue.FALSE).add("true", JsonValue.TRUE) + .add("null", JsonValue.NULL).add("doublemin", Double.MIN_VALUE) + .add("doublemax", Double.MAX_VALUE).add("intmin", Integer.MIN_VALUE) + .add("intmax", Integer.MAX_VALUE).add("longmin", Long.MIN_VALUE) + .add("longmax", Long.MAX_VALUE) + .add("bigdecimal", BigDecimal.valueOf(123456789.123456789)) + .add("biginteger", new BigInteger("123456789")) + .add("string", "string1").add("false2", false).add("true2", true) + .addNull("null2").add("object", object).add("array", array).build(); + + System.out.println("Write the JsonObject 'myJsonObject1' out to a JsonWriter"); + StringWriter sw = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sw)) { + writer.writeObject(myJsonObject1); + System.out.println("Close JsonWriter"); + } + System.out.println("Save contents of the JsonWriter as a String"); + String contents = sw.toString(); + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + contents); + System.out.println( + "Read the JsonObject back into 'myJsonObject2' using a JsonReader"); + JsonObject myJsonObject2; + try (JsonReader reader = Json.createReader(new StringReader(contents))) { + myJsonObject2 = reader.readObject(); + System.out.println("Save contents of the JsonReader as a String"); + contents = reader.toString(); + } + System.out.println("Dump contents of JsonReader as a String"); + System.out.println("JsonReaderContents=" + contents); + + System.out.println("Compare myJsonObject1 and myJsonObject2 for equality"); + pass = JSONP_Util.assertEqualsJsonObjects(myJsonObject1, myJsonObject2); + } catch (Exception e) { + throw new Fault("jsonObjectTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonObjectTest2 Failed"); + } + + /* + * @testName: jsonObjectTest3 + * + * @assertion_ids: JSONP:JAVADOC:58; JSONP:JAVADOC:61; JSONP:JAVADOC:64; + * JSONP:JAVADOC:67; JSONP:JAVADOC:70; JSONP:JAVADOC:73; JSONP:JAVADOC:76; + * JSONP:JAVADOC:80; JSONP:JAVADOC:86; JSONP:JAVADOC:215; JSONP:JAVADOC:101; + * JSONP:JAVADOC:403; JSONP:JAVADOC:264; JSONP:JAVADOC:265; JSONP:JAVADOC:436; + * JSONP:JAVADOC:400; JSONP:JAVADOC:401; JSONP:JAVADOC:402; JSONP:JAVADOC:404; + * JSONP:JAVADOC:406; JSONP:JAVADOC:408; JSONP:JAVADOC:409; JSONP:JAVADOC:439; + * JSONP:JAVADOC:441; JSONP:JAVADOC:443; JSONP:JAVADOC:527; JSONP:JAVADOC:529; + * JSONP:JAVADOC:531; JSONP:JAVADOC:533; JSONP:JAVADOC:539; + * + * @test_Strategy: Tests JsonObject/JsonObjectBuilder API's. Build a + * JsonObject using the JsonObjectBuilder API's. Verify contents of JsonObject + * using JsonObject().getJsonArray(String), + * JsonObject().getJsonNumber(String), JsonObject().getJsonObject(String), + * JsonObject().getJsonString(String), JsonObject.getInt(String) and + * JsonObject.getString(String), JsonObject.getBoolean(String), + * JsonObject.getBoolean(String, boolean), JsonObject.getInt(String, int), + * JsonObject.getString(String, String) + */ + @Test + public void jsonObjectTest3() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject object = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create sample JsonArray for testing"); + JsonArray array = JSONP_Util.createSampleJsonArray(); + + System.out.println("Create myObject JsonObject with 22 name/value pairs"); + JsonObject myObject = Json.createObjectBuilder().add("key0", -1) + .add("key1", +1).add("key2", 1).add("key3", -1e3).add("key4", +1e3) + .add("key5", 1e3).add("key6", -2E3).add("key7", +2E3).add("key8", 2E3) + .add("key9", Long.MAX_VALUE).add("key10", Long.MIN_VALUE) + .add("key11", Integer.MAX_VALUE).add("key12", Integer.MIN_VALUE) + .add("key13", Double.MAX_VALUE).add("key14", Double.MIN_VALUE) + .add("key15", BigDecimal.valueOf(123456789.123456789)) + .add("key16", new BigInteger("123456789")) + .add("key17", JsonValue.TRUE).add("key18", JsonValue.FALSE) + .add("key19", JsonValue.NULL).add("key20", JSONP_Data.asciiCharacters) + .add("key21", false).add("key22", true).addNull("key23") + .add("key24", object).add("key25", array).build(); + System.out.println("Checking intValue of key0 for correctness"); + if (!JSONP_Util.assertEquals(-1, + myObject.getJsonNumber("key0").intValue())) + pass = false; + System.out.println("key0 via JsonNumber.toString()=" + + myObject.getJsonNumber("key0").toString()); + System.out.println("Checking intValue of key1 for correctness"); + if (!JSONP_Util.assertEquals(1, myObject.getInt("key1"))) + pass = false; + System.out.println("key1 via JsonNumber.toString()=" + myObject.getInt("key1")); + System.out.println("Checking intValue of key2 for correctness"); + if (!JSONP_Util.assertEquals(1, + myObject.getJsonNumber("key2").intValue())) + pass = false; + System.out.println("key2 via JsonNumber.toString()=" + + myObject.getJsonNumber("key2").toString()); + System.out.println("Checking intValue of key3 for correctness"); + if (!JSONP_Util.assertEquals(-1000, myObject.getInt("key3"))) + pass = false; + System.out.println("key3 via JsonNumber.toString()=" + + myObject.getJsonNumber("key3").toString()); + System.out.println("Checking intValue of key4 for correctness"); + if (!JSONP_Util.assertEquals(1000, + myObject.getJsonNumber("key4").intValue())) + pass = false; + System.out.println("key4 via JsonNumber.toString()=" + + myObject.getJsonNumber("key4").toString()); + System.out.println("Checking intValue of key5 for correctness"); + if (!JSONP_Util.assertEquals(1000, + myObject.getJsonNumber("key5").intValue())) + pass = false; + System.out.println("key5 via JsonNumber.toString()=" + + myObject.getJsonNumber("key5").toString()); + System.out.println("Checking intValue of key6 for correctness"); + if (!JSONP_Util.assertEquals(-2000, + myObject.getJsonNumber("key6").intValue())) + pass = false; + System.out.println("key6 via JsonNumber.toString()=" + + myObject.getJsonNumber("key6").toString()); + System.out.println("Checking intValue of key7 for correctness"); + if (!JSONP_Util.assertEquals(2000, + myObject.getJsonNumber("key7").intValue())) + pass = false; + System.out.println("key7 via JsonNumber.toString()=" + + myObject.getJsonNumber("key7").toString()); + System.out.println("Checking intValue of key8 for correctness"); + if (!JSONP_Util.assertEquals(2000, + myObject.getJsonNumber("key8").intValue())) + pass = false; + System.out.println("key8 via JsonNumber.toString()=" + + myObject.getJsonNumber("key8").toString()); + System.out.println("Checking longValue of key9 for correctness"); + if (!JSONP_Util.assertEquals(Long.MAX_VALUE, + myObject.getJsonNumber("key9").longValue())) + pass = false; + System.out.println("LongMax via JsonNumber.toString()=" + + myObject.getJsonNumber("key9").toString()); + if (!JSONP_Util.assertEquals("" + Long.MAX_VALUE, + myObject.getJsonNumber("key9").toString())) + pass = false; + System.out.println("Checking longValue of key10 for correctness"); + if (!JSONP_Util.assertEquals(Long.MIN_VALUE, + myObject.getJsonNumber("key10").longValue())) + pass = false; + System.out.println("LongMin via JsonNumber.toString()=" + + myObject.getJsonNumber("key10").toString()); + if (!JSONP_Util.assertEquals("" + Long.MIN_VALUE, + myObject.getJsonNumber("key10").toString())) + pass = false; + System.out.println("Checking intValue of key11 for correctness"); + if (!JSONP_Util.assertEquals(Integer.MAX_VALUE, + myObject.getJsonNumber("key11").intValue())) + pass = false; + System.out.println("IntMax via JsonNumber.toString()=" + + myObject.getJsonNumber("key11").toString()); + if (!JSONP_Util.assertEquals("" + Integer.MAX_VALUE, + myObject.getJsonNumber("key11").toString())) + pass = false; + System.out.println("Checking intValue of key12 for correctness"); + if (!JSONP_Util.assertEquals(Integer.MIN_VALUE, + myObject.getJsonNumber("key12").intValue())) + pass = false; + System.out.println("IntMin via JsonNumber.toString()=" + + myObject.getJsonNumber("key12").toString()); + if (!JSONP_Util.assertEquals("" + Integer.MIN_VALUE, + myObject.getJsonNumber("key12").toString())) + pass = false; + System.out.println("Checking doubleValue of key13 for correctness"); + if (!JSONP_Util.assertEquals(Double.MAX_VALUE, + myObject.getJsonNumber("key13").doubleValue())) + pass = false; + System.out.println("Checking doubleValue of key14 for correctness"); + if (!JSONP_Util.assertEquals(Double.MIN_VALUE, + myObject.getJsonNumber("key14").doubleValue())) + pass = false; + System.out.println("Checking bigDecimalValue of key15 for correctness"); + if (!JSONP_Util.assertEquals(BigDecimal.valueOf(123456789.123456789), + myObject.getJsonNumber("key15").bigDecimalValue())) + pass = false; + System.out.println("Checking bigIntegerValue of key16 for correctness"); + if (!JSONP_Util.assertEquals(new BigInteger("123456789"), + myObject.getJsonNumber("key16").bigIntegerValue())) + pass = false; + System.out.println("Checking getBoolean of key17 for correctness"); + if (!JSONP_Util.assertEquals(true, myObject.getBoolean("key17"))) + pass = false; + System.out.println("Checking getBoolean of key18 for correctness"); + if (!JSONP_Util.assertEquals(false, myObject.getBoolean("key18"))) + pass = false; + System.out.println("Checking isNull of key19 for correctness"); + if (!JSONP_Util.assertEquals(true, myObject.isNull("key19"))) + pass = false; + System.out.println("Checking getJsonString of key20 for correctness"); + if (!JSONP_Util.assertEquals(JSONP_Data.asciiCharacters, + myObject.getJsonString("key20").getString())) + pass = false; + System.out.println("Checking getString of key20 for correctness"); + if (!JSONP_Util.assertEquals(JSONP_Data.asciiCharacters, + myObject.getString("key20"))) + pass = false; + System.out.println("Checking getBoolean of key21 for correctness"); + if (!JSONP_Util.assertEquals(false, myObject.getBoolean("key21"))) + pass = false; + System.out.println("Checking getBoolean of key22 for correctness"); + if (!JSONP_Util.assertEquals(true, myObject.getBoolean("key22"))) + pass = false; + System.out.println("Checking isNull of key23 for correctness"); + if (!JSONP_Util.assertEquals(true, myObject.isNull("key23"))) + pass = false; + System.out.println("Checking getJsonObject of key24 for correctness"); + if (!JSONP_Util.assertEqualsJsonObjects(object, + myObject.getJsonObject("key24"))) + pass = false; + System.out.println("Checking getJsonArray of key25 for correctness"); + if (!JSONP_Util.assertEqualsJsonArrays(array, + myObject.getJsonArray("key25"))) + pass = false; + + // Verify calls to JsonObject.getBoolean(int) + if (!JSONP_Util.assertEquals(true, myObject.getBoolean("key17"))) + pass = false; + if (!JSONP_Util.assertEquals(false, myObject.getBoolean("key18"))) + pass = false; + + // Verify calls to JsonObject.getBoolean(String, boolean) + System.out.println( + "Testing JsonObject.getBoolean(String, boolean) with/without default value setting."); + if (!JSONP_Util.assertEquals(true, myObject.getBoolean("key17", false))) + pass = false; + if (!JSONP_Util.assertEquals(false, myObject.getBoolean("key18", true))) + pass = false; + if (!JSONP_Util.assertEquals(true, myObject.getBoolean("key0", true))) + pass = false; + if (!JSONP_Util.assertEquals(true, myObject.getBoolean("key19", true))) + pass = false; + if (!JSONP_Util.assertEquals(true, myObject.getBoolean("key20", true))) + pass = false; + if (!JSONP_Util.assertEquals(true, myObject.getBoolean("key24", true))) + pass = false; + if (!JSONP_Util.assertEquals(true, myObject.getBoolean("key25", true))) + pass = false; + + // Verify calls to JsonObject.getInt(String, int) + System.out.println( + "Testing JsonObject.getInt(String, int) with/without default value setting."); + if (!JSONP_Util.assertEquals(-1, myObject.getInt("key0", 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myObject.getInt("key18", 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myObject.getInt("key19", 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myObject.getInt("key20", 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myObject.getInt("key24", 10))) + pass = false; + if (!JSONP_Util.assertEquals(10, myObject.getInt("key25", 10))) + pass = false; + + // Verify calls to JsonObject.getString(String, String) + System.out.println( + "Testing JsonObject.getString(String, String) with/without default value setting."); + if (!JSONP_Util.assertEquals(JSONP_Data.asciiCharacters, + myObject.getString("key20", "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myObject.getString("key0", "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myObject.getString("key18", "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myObject.getString("key19", "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myObject.getString("key24", "foo"))) + pass = false; + if (!JSONP_Util.assertEquals("foo", myObject.getString("key25", "foo"))) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonObjectTest3 Failed: ", e); + } + if (!pass) + throw new Fault("jsonObjectTest3 Failed"); + } + + /* + * @testName: jsonObjectTest4 + * + * @assertion_ids: JSONP:JAVADOC:61; JSONP:JAVADOC:70; JSONP:JAVADOC:58; + * JSONP:JAVADOC:400; JSONP:JAVADOC:401; JSONP:JAVADOC:403; JSONP:JAVADOC:404; + * JSONP:JAVADOC:406; JSONP:JAVADOC:408; JSONP:JAVADOC:409; JSONP:JAVADOC:438; + * + * @test_Strategy: Build a JsonObject and than write the JsonObject. Compare + * the Json text from the writer contents with the expected Json text output + * expected based on the JsonObject. + */ + @Test + public void jsonObjectTest4() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject myJsonObject1 = JSONP_Util.createSampleJsonObject(); + System.out.println("Write the JsonObject 'myJsonObject1' out to a JsonWriter"); + StringWriter sw = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sw)) { + writer.writeObject(myJsonObject1); + System.out.println("Close JsonWriter"); + } + System.out.println("Save contents of the JsonWriter as a String"); + String contents = sw.toString(); + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + contents); + System.out.println("Remove whitespace from contents."); + String actJsonText = JSONP_Util.removeWhitespace(contents); + System.out.println( + "Compare expected JsonObject text with actual JsonObject text for equality"); + pass = JSONP_Util.assertEqualsJsonText( + JSONP_Util.EXPECTED_SAMPLEJSONOBJECT_TEXT, actJsonText); + } catch (Exception e) { + throw new Fault("jsonObjectTest4 Failed: ", e); + } + if (!pass) + throw new Fault("jsonObjectTest4 Failed"); + } + + /* + * @testName: jsonObjectExceptionTests + * + * @assertion_ids: JSONP:JAVADOC:43; JSONP:JAVADOC:47; JSONP:JAVADOC:50; + * JSONP:JAVADOC:344; JSONP:JAVADOC:345; JSONP:JAVADOC:79; JSONP:JAVADOC:437; + * JSONP:JAVADOC:440; JSONP:JAVADOC:442; JSONP:JAVADOC:528; JSONP:JAVADOC:530; + * JSONP:JAVADOC:532; JSONP:JAVADOC:534; JSONP:JAVADOC:540; + * + * @test_Strategy: Test JSON exception conditions. Trips the exceptions: + * java.lang.ArithmeticException java.lang.ClassCastException + * java.lang.NumberFormatException java.lang.UnsupportedOperationException + * java.lang.NullPointerException + */ + @Test + public void jsonObjectExceptionTests() throws Fault { + boolean pass = true; + JsonObject testObject = null; + JsonArray testArray = null; + + try { + System.out.println("Create sample JsonObject for testing"); + testObject = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create sample JsonArray for testing"); + testArray = JSONP_Util.createSampleJsonArray(); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to JsonNumber via getJsonNumber(String)"); + JsonNumber value = testObject.getJsonNumber("address"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to JsonString via getJsonString(String)"); + JsonString value = testObject.getJsonString("address"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to JsonArray via getJsonArray(String)"); + JsonArray value = testObject.getJsonArray("address"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonArray to JsonNumber via getNumber(String)"); + JsonNumber value = testObject.getJsonNumber("phoneNumber"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonArray to JsonString via getJsonString(String)"); + JsonString value = testObject.getJsonString("phoneNumber"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to String via getString(String)"); + String value = testObject.getString("address"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonArray to String via getString(String)"); + String value = testObject.getString("phoneNumber"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonObject to int via getInt(String)"); + int value = testObject.getInt("address"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonArray to int via getInt(String)"); + int value = testObject.getInt("phoneNumber"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonArray to JsonObject via getJsonObject(String)"); + JsonObject value = testObject.getJsonObject("phoneNumber"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonNumber to JsonString via getJsonString(String)"); + JsonString value = testObject.getJsonString("age"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonNumber to JsonObject via getJsonNumber(String)"); + JsonObject value = testObject.getJsonObject("age"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonNumber to JsonArray via getJsonArray(String)"); + JsonArray value = testObject.getJsonArray("age"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonString to JsonNumber via getJsonNumber(String)"); + JsonNumber value = testObject.getJsonNumber("firstName"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonString to int via getInt(String)"); + int value = testObject.getInt("firstName"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonString to JsonObject via getJsonString(String)"); + JsonObject value = testObject.getJsonObject("firstName"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonString to JsonArray via getJsonArray(String)"); + JsonArray value = testObject.getJsonArray("firstName"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonValue.FALSE to JsonNumber via getJsonNumber(String)"); + JsonNumber value = testObject.getJsonNumber("elderly"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonValue.FALSE to JsonString via getJsonString(String)"); + JsonString value = testObject.getJsonString("elderly"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonValue.FALSE to JsonObject via getJsonObject(String)"); + JsonObject value = testObject.getJsonObject("elderly"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a JsonValue.FALSE to JsonArray via getJsonArray(String)"); + JsonArray value = testObject.getJsonArray("elderly"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a non JsonValue.FALSE|JsonValue.TRUE to boolean via getBoolean(String)"); + boolean value = testObject.getBoolean("firstName"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a non JsonValue.FALSE|JsonValue.TRUE to boolean via getBoolean(String)"); + boolean value = testObject.getBoolean("age"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a non JsonValue.FALSE|JsonValue.TRUE to boolean via getBoolean(String)"); + boolean value = testObject.getBoolean("objectOfFooBar"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip ClassCastException + try { + System.out.println( + "Trip ClassCastException trying to cast a non JsonValue.FALSE|JsonValue.TRUE to boolean via getBoolean(String)"); + boolean value = testObject.getBoolean("arrayOfFooBar"); + pass = false; + System.err.println("Failed to throw ClassCastException"); + } catch (ClassCastException e) { + System.out.println("Got expected ClassCastException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Testing NumberFormatException calling add(String, Double.NaN) + try { + System.out.println("Trip NumberFormatException calling add(String, Double.NaN)"); + JsonObject object = Json.createObjectBuilder().add("double", Double.NaN) + .build(); + pass = false; + System.err.println("Failed to throw NumberFormatException"); + } catch (NumberFormatException e) { + System.out.println("Got expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Testing NumberFormatException calling add(String, + // Double.NEGATIVE_INFINITY) + try { + System.out.println( + "Trip NumberFormatException calling add(String, Double.NEGATIVE_INFINITY)"); + JsonObject object = Json.createObjectBuilder() + .add("double", Double.NEGATIVE_INFINITY).build(); + pass = false; + System.err.println("Failed to throw NumberFormatException"); + } catch (NumberFormatException e) { + System.out.println("Got expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Testing NumberFormatException calling add(String, + // Double.POSITIVE_INFINITY) + try { + System.out.println( + "Trip NumberFormatException calling add(String, Double.POSITIVE_INFINITY)"); + JsonObject object = Json.createObjectBuilder() + .add("double", Double.POSITIVE_INFINITY).build(); + pass = false; + System.err.println("Failed to throw NumberFormatException"); + } catch (NumberFormatException e) { + System.out.println("Got expected NumberFormatException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test for ArithmeticException + try { + System.out.println( + "Trip ArithmeticException calling add(\"number\", 12345.12345) and attempting to extract as an exact integer value"); + JsonObject object = Json.createObjectBuilder().add("number", 12345.12345) + .build(); + System.out.println("Call JsonObject.getJsonNumber(\"number\").intValueExact()"); + int value = object.getJsonNumber("number").intValueExact(); + pass = false; + System.err.println("Failed to throw ArithmeticException"); + } catch (ArithmeticException e) { + System.out.println("Got expected ArithmeticException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test for ArithmeticException + try { + System.out.println( + "Trip ArithmeticException calling add(\"number\", 12345.12345) and attempting to extract as an exact long value"); + JsonObject object = Json.createObjectBuilder().add("number", 12345.12345) + .build(); + System.out.println("Call JsonObject.getJsonNumber(\"number\").longValueExact()"); + long value = object.getJsonNumber("number").longValueExact(); + pass = false; + System.err.println("Failed to throw ArithmeticException"); + } catch (ArithmeticException e) { + System.out.println("Got expected ArithmeticException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Test for ArithmeticException + try { + System.out.println( + "Trip ArithmeticException calling add(\"number\", 12345.12345) and attempting to extract as an exact biginteger value"); + JsonObject object = Json.createObjectBuilder().add("number", 12345.12345) + .build(); + System.out.println( + "Call JsonObject.getJsonNumber(\"number\").bigIntegerValueExact()"); + BigInteger value = object.getJsonNumber("number").bigIntegerValueExact(); + pass = false; + System.err.println("Failed to throw ArithmeticException"); + } catch (ArithmeticException e) { + System.out.println("Got expected ArithmeticException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Tests for UnsupportedOperationException using Collection methods to + // modify JsonObject Map + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonObject.put(K,V) trying to modify JsonObject map which should be immutable"); + testObject.put("foo", JsonValue.FALSE); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonObject.putAll(Map) trying to modify JsonObject map which should be immutable"); + testObject.putAll(testObject); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonObject.clear() trying to modify JsonObject map which should be immutable"); + testObject.clear(); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip UnsupportedOperationException + try { + System.out.println( + "Trip UnsupportedOperationException JsonObject.remove(K) trying to modify JsonObject map which should be immutable"); + testObject.remove("firstName"); + pass = false; + System.err.println("Failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + System.out.println("Got expected UnsupportedOperationException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObject.getBoolean(String) when no mapping exists for name."); + boolean value = testObject.getBoolean("foo"); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObject.getInt(String) when no mapping exists for name."); + int value = testObject.getInt("foo"); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObject.getString(String) when no mapping exists for name."); + String value = testObject.getString("foo"); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObject.isNull(String) when no mapping exists for name."); + boolean value = testObject.isNull("foo"); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonObjectExceptionTests Failed"); + } + + /* + * @testName: jsonObjectNullNameValueExceptionTests + * + * @assertion_ids: JSONP:JAVADOC:561; JSONP:JAVADOC:562; JSONP:JAVADOC:563; + * JSONP:JAVADOC:564; JSONP:JAVADOC:565; JSONP:JAVADOC:566; JSONP:JAVADOC:567; + * JSONP:JAVADOC:568; JSONP:JAVADOC:569; JSONP:JAVADOC:570; JSONP:JAVADOC:571; + * + * @test_Strategy: Test JSON NPE exception conditions when attempting to add a + * specified name or value that is null. + */ + @Test + public void jsonObjectNullNameValueExceptionTests() throws Fault { + boolean pass = true; + JsonObjectBuilder job = Json.createObjectBuilder(); + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, JsonValue) when name is null."); + job.add(null, JsonValue.TRUE); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, JsonValue) when value is null."); + job.add("name", (JsonValue) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, String) when name is null."); + job.add(null, "value"); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, String) when value is null."); + job.add("name", (String) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, BigInteger) when name is null."); + job.add(null, new BigInteger("123456789")); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, BigInteger) when value is null."); + job.add("name", (BigInteger) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, BigDecimal) when name is null."); + job.add(null, new BigDecimal("123456789")); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, BigDecimal) when value is null."); + job.add("name", (BigDecimal) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, int) when name is null."); + job.add(null, 123456789); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, long) when name is null."); + job.add(null, 123456789L); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, double) when name is null."); + job.add(null, 123456.789); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObject.add(String, boolean) when name is null."); + job.add(null, true); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObject.addNull(String) when name is null."); + job.addNull(null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, JsonObjectBuilder) when name is null."); + job.add(null, Json.createObjectBuilder()); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonObjectBuilder.add(String, JsonObjectBuilder) when value is null."); + job.add("name", (JsonObjectBuilder) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonArrayBuilder.add(String, JsonArrayBuilder) when name is null."); + job.add(null, Json.createArrayBuilder()); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NullPointerException + try { + System.out.println( + "Trip NullPointerException for JsonArrayBuilder.add(String, JsonArrayBuilder) when value is null."); + job.add("name", (JsonArrayBuilder) null); + pass = false; + System.err.println("Failed to throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonObjectNullNameValueExceptionTests Failed"); + } + + /* + * @testName: jsonCreateObjectBuilder11Test + * + * @assertion_ids: JSONP:JAVADOC:577; JSONP:JAVADOC:578; JSONP:JAVADOC:656; + * JSONP:JAVADOC:657; + * + * @test_Strategy: Tests JsonObjectBuilder API factory methods added in JSON-P + * 1.1. + */ + @Test + public void jsonCreateObjectBuilder11Test() throws Fault { + CreateObjectBuilder createTest = new CreateObjectBuilder(); + final TestResult result = createTest.test(); + result.eval(); + } + + /* + * @testName: jsonObjectBuilder11Test + * + * @assertion_ids: JSONP:JAVADOC:618; JSONP:JAVADOC:619; + * + * @test_Strategy: Tests JsonObjectBuilder API methods added in JSON-P 1.1. + */ + @Test + public void jsonObjectBuilder11Test() throws Fault { + ObjectBuild buildTest = new ObjectBuild(); + final TestResult result = buildTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonobjecttests/CreateObjectBuilder.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonobjecttests/CreateObjectBuilder.java new file mode 100644 index 0000000..f4b370c --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonobjecttests/CreateObjectBuilder.java
@@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonobjecttests; + +import jakarta.jsonp.tck.api.common.TestResult; +import java.util.HashMap; +import java.util.Map; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests: + * {@link JsonObjectBuilder} API factory methods added in JSON-P 1.1.<br> + */ +public class CreateObjectBuilder { + + /** + * Test {@link JsonObjectBuilder} factory method added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonObjectBuilder API factory methods added in JSON-P 1.1."); + System.out.println("JsonObjectBuilder API factory methods added in JSON-P 1.1."); + testCreateFromMap(result); + testCreateFromJsonObject(result); + return result; + } + + /** + * Test {@link Json#createObjectBuilder(Map<String,Object>)} method. + * + * @param result + * Test suite result. + */ + private void testCreateFromMap(final TestResult result) { + System.out.println(" - Json#createObjectBuilder(Map<String,Object>)"); + final JsonObject check = createSimpleObjectWithStr(); + Map<String, Object> values = new HashMap<>(2); + values.put(DEF_NAME, DEF_VALUE); + values.put(STR_NAME, STR_VALUE); + final JsonObjectBuilder builder = Json.createObjectBuilder(values); + final JsonObject out = builder.build(); + if (operationFailed(check, out)) { + result.fail("createObjectBuilder(Map<String,Object>)", "Builder output " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Test {@link Json#createObjectBuilder(JsonObject)} method. + * + * @param result + * Test suite result. + */ + private void testCreateFromJsonObject(final TestResult result) { + System.out.println(" - Json#createObjectBuilder(JsonObject)"); + final JsonObject check = createSimpleObjectWithStr(); + final JsonObjectBuilder builder = Json.createObjectBuilder(check); + final JsonObject out = builder.build(); + if (operationFailed(check, out)) { + result.fail("reateObjectBuilder(JsonObject)", "Builder output " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonobjecttests/ObjectBuild.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonobjecttests/ObjectBuild.java new file mode 100644 index 0000000..88f7127 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonobjecttests/ObjectBuild.java
@@ -0,0 +1,303 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonobjecttests; + +import jakarta.jsonp.tck.api.common.ObjectBuilder; +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests for {@link JsonObject} + * and {@link JsonObjectBuilder}. + */ +public class ObjectBuild { + + /** + * {@link JsonArrayBuilder} API remove() methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonObjectBuilder API methods added in JSON-P 1.1."); + System.out.println("JsonObjectBuilder API methods added in JSON-P 1.1."); + testAddString(result); + testAddInt(result); + testAddBool(result); + testAddObject(result); + testAddAllNull(result); + testRemoveString(result); + testRemoveInt(result); + testRemoveBool(result); + testRemoveObject(result); + testRemoveNull(result); + return result; + } + + /** + * Test {@code JsonArrayBuilder addAll(JsonObjectBuilder)} method on + * {@code String} value. + * + * @param result + * Test suite result. + */ + private void testAddString(final TestResult result) { + System.out.println(" - addAll(JsonObjectBuilder) for String"); + final JsonObjectBuilder target = ObjectBuilder + .add(Json.createObjectBuilder(), DEF_NAME, DEF_VALUE); + final JsonObjectBuilder arg = ObjectBuilder.add(Json.createObjectBuilder(), + STR_NAME, STR_VALUE); + final JsonObject check = createSimpleObjectWithStr(); + verifyAddAll(result, check, target, arg); + } + + /** + * Test {@code JsonArrayBuilder addAll(JsonObjectBuilder)} method on + * {@code int} value. + * + * @param result + * Test suite result. + */ + private void testAddInt(final TestResult result) { + System.out.println(" - addAll(JsonObjectBuilder) for int"); + final JsonObjectBuilder target = ObjectBuilder + .add(Json.createObjectBuilder(), DEF_NAME, DEF_VALUE); + final JsonObjectBuilder arg = ObjectBuilder.add(Json.createObjectBuilder(), + INT_NAME, INT_VALUE); + final JsonObject check = createSimpleObjectWithInt(); + verifyAddAll(result, check, target, arg); + } + + /** + * Test {@code JsonArrayBuilder addAll(JsonObjectBuilder)} method on + * {@code boolean} value. + * + * @param result + * Test suite result. + */ + private void testAddBool(final TestResult result) { + System.out.println(" - addAll(JsonObjectBuilder) for boolean"); + final JsonObjectBuilder target = ObjectBuilder + .add(Json.createObjectBuilder(), DEF_NAME, DEF_VALUE); + final JsonObjectBuilder arg = ObjectBuilder.add(Json.createObjectBuilder(), + BOOL_NAME, BOOL_VALUE); + final JsonObject check = createSimpleObjectWithBool(); + verifyAddAll(result, check, target, arg); + } + + /** + * Test {@code JsonArrayBuilder addAll(JsonObjectBuilder)} method on + * {@code JsonObject} value. + * + * @param result + * Test suite result. + */ + private void testAddObject(final TestResult result) { + System.out.println(" - addAll(JsonObjectBuilder) for JsonObject"); + final JsonObjectBuilder target = ObjectBuilder + .add(Json.createObjectBuilder(), DEF_NAME, DEF_VALUE) + .add(DEF_OBJ_NAME, DEF_OBJ_VALUE); + final JsonObjectBuilder arg = ObjectBuilder.add(Json.createObjectBuilder(), + OBJ_NAME, OBJ_VALUE); + final JsonObject check = createCompoundObjectWithObject(); + verifyAddAll(result, check, target, arg); + } + + /** + * Test {@code JsonObjectBuilder addAll(JsonObjectBuilder)} method with + * {@code null} builder argument. + * + * @param result + * Test suite result. + */ + private void testAddAllNull(final TestResult result) { + System.out.println(" - addAll(JsonObjectBuilder) for null builder argument"); + JsonObjectBuilder builder = Json.createObjectBuilder(); + try { + builder.addAll((JsonObjectBuilder) null); + result.fail("addAll(null)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("addAll(null)", + "Calling method with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Test {@code JsonObjectBuilder remove(String)} method on {@code String} + * value. + * + * @param result + * Test suite result. + */ + private void testRemoveString(final TestResult result) { + System.out.println(" - remove(String) for String"); + final JsonObjectBuilder in = ObjectBuilder + .add(Json.createObjectBuilder(), DEF_NAME, DEF_VALUE) + .add(STR_NAME, STR_VALUE); + final JsonObjectBuilder builder = in.remove(STR_NAME); + final JsonObject check = createSimpleObject(); + verifyRemovel(result, check, builder); + } + + /** + * Test {@code JsonObjectBuilder remove(String)} method on {@code int} value. + * + * @param result + * Test suite result. + */ + private void testRemoveInt(final TestResult result) { + System.out.println(" - remove(String) for int"); + final JsonObjectBuilder in = ObjectBuilder + .add(Json.createObjectBuilder(), DEF_NAME, DEF_VALUE) + .add(INT_NAME, INT_VALUE); + final JsonObjectBuilder builder = in.remove(INT_NAME); + final JsonObject check = createSimpleObject(); + verifyRemovel(result, check, builder); + } + + /** + * Test {@code JsonObjectBuilder remove(String)} method on {@code boolean} + * value. + * + * @param result + * Test suite result. + */ + private void testRemoveBool(final TestResult result) { + System.out.println(" - remove(String) for boolean"); + final JsonObjectBuilder in = ObjectBuilder + .add(Json.createObjectBuilder(), DEF_NAME, DEF_VALUE) + .add(BOOL_NAME, BOOL_VALUE); + final JsonObjectBuilder builder = in.remove(BOOL_NAME); + final JsonObject check = createSimpleObject(); + verifyRemovel(result, check, builder); + } + + /** + * Test {@code JsonObjectBuilder remove(String)} method on {@code JsonObject} + * value. + * + * @param result + * Test suite result. + */ + private void testRemoveObject(final TestResult result) { + System.out.println(" - remove(String) for JsonObject"); + final JsonObjectBuilder in = ObjectBuilder + .add(Json.createObjectBuilder(), DEF_NAME, DEF_VALUE) + .add(DEF_OBJ_NAME, DEF_OBJ_VALUE).add(OBJ_NAME, OBJ_VALUE); + final JsonObjectBuilder builder = in.remove(OBJ_NAME); + final JsonObject check = createCompoundObject(); + verifyRemovel(result, check, builder); + } + + /** + * Test {@code JsonObjectBuilder remove(String)} method with {@code null} + * name. + * + * @param result + * Test suite result. + */ + private void testRemoveNull(final TestResult result) { + System.out.println(" - remove(String) for null name argument"); + JsonObjectBuilder builder = Json.createObjectBuilder(); + try { + builder.remove((String) null); + result.fail("remove(null)", + "Calling method with null argument shall throw NullPointerException"); + } catch (NullPointerException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("remove(null)", + "Calling method with null argument shall throw NullPointerException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Test helper: Verify {@code JsonObjectBuilder addAll(JsonObjectBuilder)} + * method on provided builders. + * + * @param result + * Test suite result. + * @param check + * Expected value (used for operation check). + * @param target + * Builder instance used to call {@code addAll(JsonObjectBuilder)} + * method. + * @param arg + * Builder instance passed as an argument. + */ + private void verifyAddAll(final TestResult result, final JsonObject check, + JsonObjectBuilder target, final JsonObjectBuilder arg) { + target.addAll(arg); + final JsonObject out = target.build(); + if (operationFailed(check, out)) { + result.fail("addAll(JsonObjectBuilder)", "Output builder " + + valueToString(out) + " value shall be " + valueToString(check)); + } + } + + /** + * Test helper: Verify {@code JsonObjectBuilder remove(String)} method on + * provided builder. + * + * @param result + * Test suite result. + * @param check + * Expected value (used for operation check). + * @param builder + * Builder instance after {@code JsonObjectBuilder remove(String)} + * method was called. + * @param arg + * Builder instance passed as an argument. + */ + private void verifyRemovel(final TestResult result, final JsonObject check, + JsonObjectBuilder builder) { + final JsonObject out = builder.build(); + if (operationFailed(check, out)) { + result.fail("remove(String)", "Output builder " + valueToString(out) + + " value shall be " + valueToString(check)); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparsereventtests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparsereventtests/ClientTests.java new file mode 100644 index 0000000..2da56f5 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparsereventtests/ClientTests.java
@@ -0,0 +1,136 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonparsereventtests; + +import jakarta.json.stream.*; + +import java.io.*; +import java.util.*; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonValueOfTest + * + * @assertion_ids: JSONP:JAVADOC:128; + * + * @test_Strategy: Test JsonParser.Event.valueOf() API method call with all + * JsonParser.Event types. + * + */ + @Test + public void jsonValueOfTest() throws Fault { + boolean pass = true; + + String eventTypeStrings[] = { "END_ARRAY", "END_OBJECT", "KEY_NAME", + "START_ARRAY", "START_OBJECT", "VALUE_FALSE", "VALUE_NULL", + "VALUE_NUMBER", "VALUE_STRING", "VALUE_TRUE" }; + + for (String eventTypeString : eventTypeStrings) { + JsonParser.Event eventType; + try { + System.out.println( + "Testing enum value for string constant name " + eventTypeString); + eventType = JsonParser.Event.valueOf(eventTypeString); + System.out.println("Got enum type " + eventType + " for enum string constant named " + + eventTypeString); + } catch (Exception e) { + System.err.println("Caught unexpected exception: " + e); + pass = false; + } + + } + + System.out.println("Testing negative test case for NullPointerException"); + try { + JsonParser.Event.valueOf(null); + System.err.println("did not get expected NullPointerException"); + pass = false; + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + System.err.println("Got unexpected exception " + e); + pass = false; + } + + System.out.println("Testing negative test case for IllegalArgumentException"); + try { + JsonParser.Event.valueOf("INVALID"); + System.err.println("did not get expected IllegalArgumentException"); + pass = false; + } catch (IllegalArgumentException e) { + System.out.println("Got expected IllegalArgumentException"); + } catch (Exception e) { + System.err.println("Got unexpected exception " + e); + pass = false; + } + + if (!pass) + throw new Fault("jsonValueOfTest Failed"); + } + + /* + * @testName: jsonValuesTest + * + * @assertion_ids: JSONP:JAVADOC:129; + * + * @test_Strategy: Test JsonParser.Event.values() API method call and verify + * enums returned. + * + */ + @Test + public void jsonValuesTest() throws Fault { + boolean pass = true; + + System.out.println( + "Testing API method JsonParser.Event.values() to return array of enums."); + JsonParser.Event[] values = JsonParser.Event.values(); + + for (JsonParser.Event eventType : values) { + String eventString = JSONP_Util.getEventTypeString(eventType); + if (eventString == null) { + System.err.println("Got no value for enum " + eventType); + pass = false; + } else + System.out.println("Got " + eventString + " for enum " + eventType); + } + + if (!pass) + throw new Fault("jsonValuesTest Failed"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparserfactorytests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparserfactorytests/ClientTests.java new file mode 100644 index 0000000..d8a2b7a --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparserfactorytests/ClientTests.java
@@ -0,0 +1,580 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id: Client.java 66863 2012-07-23 11:26:40Z adf $ + */ +package jakarta.jsonp.tck.api.jsonparserfactorytests; + +import jakarta.json.*; +import jakarta.json.stream.*; +import java.io.*; +import java.nio.charset.Charset; + +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; +import java.util.Iterator; +import java.util.Map; +import java.util.ArrayList; + +import jakarta.json.stream.JsonParser.Event.*; +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonParserFactoryTest1 + * + * @assertion_ids: JSONP:JAVADOC:417; JSONP:JAVADOC:164; + * + * @test_Strategy: Tests the JsonParserFactory API. + * + * JsonParserFactory parserFactory = Json.createParserFactory(Map<String, ?>); + * JsonParser parser1 = parserFactory.createParser(Reader) JsonParser parser2 + * = parserFactory.createParser(Reader) + */ + @Test + public void jsonParserFactoryTest1() throws Fault { + boolean pass = true; + JsonParser parser1 = null; + JsonParser parser2 = null; + JsonParser.Event event = null; + try { + System.out.println("Create JsonParserFactory with a configuration"); + JsonParserFactory parserFactory = Json + .createParserFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = parserFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("--------------------------------------------------"); + System.out.println("TEST CASE [JsonParserFactory.createParser(Reader)]"); + System.out.println("--------------------------------------------------"); + String jsonObjectString = "{\"foo\":\"bar\"}"; + System.out.println("Create 1st JsonParser from the Reader using JsonParserFactory"); + parser1 = parserFactory.createParser(new StringReader(jsonObjectString)); + if (parser1 == null) { + System.err.println("ParserFactory failed to create parser1 from Reader"); + pass = false; + } else { + System.out.println("Parsing " + jsonObjectString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser1, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser1, "foo", "bar"); + JSONP_Util.testEventType(parser1, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + + System.out.println("Create 2nd JsonParser from the Reader using JsonParserFactory"); + parser2 = parserFactory.createParser(new StringReader(jsonObjectString)); + if (parser2 == null) { + System.err.println("ParserFactory failed to create parser2 from Reader"); + pass = false; + } else { + System.out.println("Parsing " + jsonObjectString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser2, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser2, "foo", "bar"); + JSONP_Util.testEventType(parser2, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + + } catch (Exception e) { + throw new Fault("jsonParserFactoryTest1 Failed: ", e); + } finally { + try { + parser1.close(); + parser2.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserFactoryTest1 Failed"); + } + + /* + * @testName: jsonParserFactoryTest2 + * + * @assertion_ids: JSONP:JAVADOC:417; JSONP:JAVADOC:166; + * + * @test_Strategy: Tests the JsonParserFactory API. + * + * JsonParserFactory parserFactory = Json.createParserFactory(Map<String, ?>); + * JsonParser parser1 = parserFactory.createParser(JsonObject) JsonParser + * parser2 = parserFactory.createParser(JsonObject) + */ + @Test + public void jsonParserFactoryTest2() throws Fault { + boolean pass = true; + JsonParser parser1 = null; + JsonParser parser2 = null; + JsonParser.Event event = null; + try { + System.out.println("Create JsonParserFactory with a configuration"); + JsonParserFactory parserFactory = Json + .createParserFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = parserFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("------------------------------------------------------"); + System.out.println("TEST CASE [JsonParserFactory.createParser(JsonObject)]"); + System.out.println("------------------------------------------------------"); + String jsonObjectString = "{\"foo\":\"bar\"}"; + JsonObject jsonObj = JSONP_Util + .createJsonObjectFromString(jsonObjectString); + System.out.println( + "Create 1st JsonParser from the JsonObject using JsonParserFactory"); + parser1 = parserFactory.createParser(jsonObj); + if (parser1 == null) { + System.err.println("ParserFactory failed to create parser1 from JsonObject"); + pass = false; + } else { + System.out.println("Parsing " + jsonObjectString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser1, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser1, "foo", "bar"); + JSONP_Util.testEventType(parser1, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + + System.out.println( + "Create 2nd JsonParser from the JsonObject using JsonParserFactory"); + parser2 = parserFactory.createParser(jsonObj); + if (parser2 == null) { + System.err.println("ParserFactory failed to create parser2 from JsonObject"); + pass = false; + } else { + System.out.println("Parsing " + jsonObjectString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser2, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser2, "foo", "bar"); + JSONP_Util.testEventType(parser2, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + + } catch (Exception e) { + throw new Fault("jsonParserFactoryTest2 Failed: ", e); + } finally { + try { + parser1.close(); + parser2.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserFactoryTest2 Failed"); + } + + /* + * @testName: jsonParserFactoryTest3 + * + * @assertion_ids: JSONP:JAVADOC:417; JSONP:JAVADOC:167; + * + * @test_Strategy: Tests the JsonParserFactory API. + * + * JsonParserFactory parserFactory = Json.createParserFactory(Map<String, ?>); + * JsonParser parser1 = parserFactory.createParser(JsonArray) JsonParser + * parser2 = parserFactory.createParser(JsonArray) + */ + @Test + public void jsonParserFactoryTest3() throws Fault { + boolean pass = true; + JsonParser parser1 = null; + JsonParser parser2 = null; + JsonParser.Event event = null; + try { + System.out.println("Create JsonParserFactory with a configuration"); + JsonParserFactory parserFactory = Json + .createParserFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = parserFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("-----------------------------------------------------"); + System.out.println("TEST CASE [JsonParserFactory.createParser(JsonArray)]"); + System.out.println("-----------------------------------------------------"); + String jsonArrayString = "[\"foo\",\"bar\"]"; + JsonArray jsonArr = JSONP_Util.createJsonArrayFromString(jsonArrayString); + System.out.println( + "Create 1st JsonParser from the JsonArray using JsonParserFactory"); + parser1 = parserFactory.createParser(jsonArr); + if (parser1 == null) { + System.err.println("ParserFactory failed to create parser1 from JsonArray"); + pass = false; + } else { + System.out.println("Parsing " + jsonArrayString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser1, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser1, "foo"); + JSONP_Util.testStringValue(parser1, "bar"); + JSONP_Util.testEventType(parser1, JsonParser.Event.END_ARRAY); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + + System.out.println( + "Create 2nd JsonParser from the JsonArray using JsonParserFactory"); + parser2 = parserFactory.createParser(jsonArr); + if (parser2 == null) { + System.err.println("ParserFactory failed to create parser2 from JsonArray"); + pass = false; + } else { + System.out.println("Parsing " + jsonArrayString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser2, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser2, "foo"); + JSONP_Util.testStringValue(parser2, "bar"); + JSONP_Util.testEventType(parser2, JsonParser.Event.END_ARRAY); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + } catch (Exception e) { + throw new Fault("jsonParserFactoryTest3 Failed: ", e); + } finally { + try { + parser1.close(); + parser2.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserFactoryTest3 Failed"); + } + + /* + * @testName: jsonParserFactoryTest4 + * + * @assertion_ids: JSONP:JAVADOC:417; JSONP:JAVADOC:165; + * + * @test_Strategy: Tests the JsonParserFactory API. + * + * JsonParserFactory parserFactory = Json.createParserFactory(Map<String, ?>); + * JsonParser parser1 = parserFactory.createParser(InputStream) JsonParser + * parser2 = parserFactory.createParser(InputStream) + */ + @Test + public void jsonParserFactoryTest4() throws Fault { + boolean pass = true; + JsonParser parser1 = null; + JsonParser parser2 = null; + JsonParser.Event event = null; + try { + System.out.println("Create JsonParserFactory with a configuration"); + JsonParserFactory parserFactory = Json + .createParserFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = parserFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("-------------------------------------------------------"); + System.out.println("TEST CASE [JsonParserFactory.createParser(InputStream)]"); + System.out.println("-------------------------------------------------------"); + String jsonObjectString = "{\"foo\":\"bar\"}"; + System.out.println( + "Create 1st JsonParser from the InputStream using JsonParserFactory"); + parser1 = parserFactory.createParser(new ByteArrayInputStream( + jsonObjectString.getBytes(JSONP_Util.UTF_8))); + if (parser1 == null) { + System.err.println("ParserFactory failed to create parser1 from InputStream"); + pass = false; + } else { + System.out.println("Parsing " + jsonObjectString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser1, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser1, "foo", "bar"); + JSONP_Util.testEventType(parser1, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + + System.out.println( + "Create 2nd JsonParser from the InputStream using JsonParserFactory"); + parser2 = parserFactory.createParser(new ByteArrayInputStream( + jsonObjectString.getBytes(JSONP_Util.UTF_8))); + if (parser2 == null) { + System.err.println("ParserFactory failed to create parser2 from InputStream"); + pass = false; + } else { + System.out.println("Parsing " + jsonObjectString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser2, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser2, "foo", "bar"); + JSONP_Util.testEventType(parser2, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + + } catch (Exception e) { + throw new Fault("jsonParserFactoryTest4 Failed: ", e); + } finally { + try { + parser1.close(); + parser2.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserFactoryTest4 Failed"); + } + + /* + * @testName: jsonParserFactoryTest5 + * + * @assertion_ids: JSONP:JAVADOC:417; JSONP:JAVADOC:201; + * + * @test_Strategy: Tests the JsonParserFactory API. + * + * JsonParserFactory parserFactory = Json.createParserFactory(Map<String, ?>); + * JsonParser parser1 = parserFactory.createParser(InputStream, Charset) + * JsonParser parser2 = parserFactory.createParser(InputStream, Charset) + */ + @Test + public void jsonParserFactoryTest5() throws Fault { + boolean pass = true; + JsonParser parser1 = null; + JsonParser parser2 = null; + JsonParser.Event event = null; + try { + System.out.println("Create JsonParserFactory with a configuration"); + JsonParserFactory parserFactory = Json + .createParserFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = parserFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println( + "----------------------------------------------------------------"); + System.out.println( + "TEST CASE [JsonParserFactory.createParser(InputStream, Charset)]"); + System.out.println( + "----------------------------------------------------------------"); + String jsonObjectString = "{\"foo\":\"bar\"}"; + System.out.println( + "Create 1st JsonParser from the InputStream using JsonParserFactory"); + parser1 = parserFactory.createParser( + new ByteArrayInputStream(jsonObjectString.getBytes(JSONP_Util.UTF_8)), + JSONP_Util.UTF_8); + if (parser1 == null) { + System.err.println("ParserFactory failed to create parser1 from InputStream"); + pass = false; + } else { + System.out.println("Parsing " + jsonObjectString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser1, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser1, "foo", "bar"); + JSONP_Util.testEventType(parser1, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + + System.out.println( + "Create 2nd JsonParser from the InputStream using JsonParserFactory"); + parser2 = parserFactory.createParser( + new ByteArrayInputStream(jsonObjectString.getBytes(JSONP_Util.UTF_8)), + JSONP_Util.UTF_8); + if (parser2 == null) { + System.err.println("ParserFactory failed to create parser2 from InputStream"); + pass = false; + } else { + System.out.println("Parsing " + jsonObjectString); + System.out.println("Verify that JSON Parser Events/Data matches"); + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser2, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser2, "foo", "bar"); + JSONP_Util.testEventType(parser2, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } + + } catch (Exception e) { + throw new Fault("jsonParserFactoryTest5 Failed: ", e); + } finally { + try { + parser1.close(); + parser2.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserFactoryTest5 Failed"); + } + + /* + * @testName: jsonParserFactoryTest6 + * + * @assertion_ids: JSONP:JAVADOC:417; JSONP:JAVADOC:164; JSONP:JAVADOC:428; + * + * @test_Strategy: Tests the JsonParserFactory API. + * + * JsonParserFactory parserFactory = Json.createParserFactory(Map<String, ?>); + * Map<String, ?> config = JsonParserFactory.getConfigInUse(); + * + * Test for the following 2 scenarios: 1) no supported provider property + * (empty config) 2) non supported provider property + */ + @Test + public void jsonParserFactoryTest6() throws Fault { + boolean pass = true; + JsonParserFactory parserFactory; + Map<String, ?> config; + try { + System.out.println("----------------------------------------------"); + System.out.println("Test scenario1: no supported provider property"); + System.out.println("----------------------------------------------"); + System.out.println("Create JsonParserFactory with Map<String, ?> with EMPTY config"); + parserFactory = Json.createParserFactory(JSONP_Util.getEmptyConfig()); + config = parserFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("-----------------------------------------------"); + System.out.println("Test scenario2: non supported provider property"); + System.out.println("-----------------------------------------------"); + System.out.println("Create JsonParserFactory with Map<String, ?> with FOO config"); + parserFactory = Json.createParserFactory(JSONP_Util.getFooConfig()); + config = parserFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonParserFactoryTest6 Failed: ", e); + } + if (!pass) + throw new Fault("jsonParserFactoryTest6 Failed"); + } + + /* + * @testName: jsonParserFactoryExceptionTest + * + * @assertion_ids: JSONP:JAVADOC:225; + * + * @test_Strategy: Test JsonParserFactory exception conditions. Trip the + * following exception due to unknown encoding or i/o error: + * + * jakarta.json.JsonException + */ + @Test + public void jsonParserFactoryExceptionTest() throws Fault { + boolean pass = true; + + // Tests JsonParserFactory.createParser(InputStream) for JsonException if + // i/o error + try { + System.out.println( + "Tests JsonParserFactory.createParser(InputStream) for JsonException if i/o error."); + JsonParserFactory parserFactory = Json + .createParserFactory(JSONP_Util.getEmptyConfig()); + MyBufferedInputStream mbi = new MyBufferedInputStream( + JSONP_Util.getInputStreamFromString("{}"), true); + JsonParser parser = parserFactory.createParser(mbi); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Tests JsonParserFactory.createParser(InputStream) for JsonException if + // unknown encoding + try { + System.out.println( + "Tests JsonParserFactory.createParser(InputStream) for JsonException if unknown encoding."); + JsonParserFactory parserFactory = Json + .createParserFactory(JSONP_Util.getEmptyConfig()); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectUnknownEncoding.json"); + JsonParser parser = parserFactory.createParser(is); + System.out.println("parser=" + parser); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonParserFactoryExceptionTest Failed"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparsertests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparsertests/ClientTests.java new file mode 100644 index 0000000..c1a3f0e --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparsertests/ClientTests.java
@@ -0,0 +1,1908 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonparsertests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +import java.io.*; +import java.math.BigDecimal; +import java.util.NoSuchElementException; +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.json.*; +import jakarta.json.stream.*; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* + * Utitity method to parse various JsonObjectUTF encoded files + */ + private boolean parseAndVerify_JsonObjectUTF(JsonParser parser) + throws Exception { + boolean pass = true; + + try { + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser, "stringName", "stringValue"); + JSONP_Util.testKeyStartObjectValue(parser, "objectName"); + JSONP_Util.testKeyStringValue(parser, "foo", "bar"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testKeyStartArrayValue(parser, "arrayName"); + JSONP_Util.testIntegerValue(parser, 1); + JSONP_Util.testIntegerValue(parser, 2); + JSONP_Util.testIntegerValue(parser, 3); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } catch (Exception e) { + throw e; + } + return pass; + } + + /* + * Utitity method to parse JsonObjectWithAllTypesOfData + */ + private boolean parseAndVerify_JsonObjectWithAllTypesOfData(JsonParser parser) + throws Exception { + boolean pass = true; + + try { + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser, "emptyString", ""); + JSONP_Util.testKeyStartArrayValue(parser, "emptyArray"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testKeyStartObjectValue(parser, "emptyObject"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testKeyStringValue(parser, "string", "string"); + JSONP_Util.testKeyIntegerValue(parser, "number", 100); + JSONP_Util.testKeyTrueValue(parser, "true"); + JSONP_Util.testKeyFalseValue(parser, "false"); + JSONP_Util.testKeyNullValue(parser, "null"); + JSONP_Util.testKeyStartObjectValue(parser, "object"); + JSONP_Util.testKeyStringValue(parser, "emptyString", ""); + JSONP_Util.testKeyStartArrayValue(parser, "emptyArray"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testKeyStartObjectValue(parser, "emptyObject"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testKeyStringValue(parser, "string", "string"); + JSONP_Util.testKeyIntegerValue(parser, "number", 100); + JSONP_Util.testKeyTrueValue(parser, "true"); + JSONP_Util.testKeyFalseValue(parser, "false"); + JSONP_Util.testKeyNullValue(parser, "null"); + JSONP_Util.testKeyStartObjectValue(parser, "object"); + JSONP_Util.testKeyStringValue(parser, "name", "value"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testKeyStartArrayValue(parser, "array"); + JSONP_Util.testStringValue(parser, "one"); + JSONP_Util.testStringValue(parser, "two"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testKeyStartArrayValue(parser, "array"); + JSONP_Util.testStringValue(parser, "string"); + JSONP_Util.testIntegerValue(parser, 100); + JSONP_Util.testTrueValue(parser, JsonParser.Event.VALUE_TRUE); + JSONP_Util.testFalseValue(parser, JsonParser.Event.VALUE_FALSE); + JSONP_Util.testNullValue(parser, JsonParser.Event.VALUE_NULL); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser, "name", "value"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser, "one"); + JSONP_Util.testStringValue(parser, "two"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testKeyIntegerValue(parser, "intPositive", 100); + JSONP_Util.testKeyIntegerValue(parser, "intNegative", -100); + JSONP_Util.testKeyLongValue(parser, "longMax", 9223372036854775807L); + JSONP_Util.testKeyLongValue(parser, "longMin", -9223372036854775808L); + JSONP_Util.testKeyDoubleValue(parser, "fracPositive", (double) 0.5); + JSONP_Util.testKeyDoubleValue(parser, "fracNegative", (double) -0.5); + JSONP_Util.testKeyDoubleValue(parser, "expPositive1", (double) 7e3); + JSONP_Util.testKeyDoubleValue(parser, "expPositive2", (double) 7e+3); + JSONP_Util.testKeyDoubleValue(parser, "expPositive3", (double) 9E3); + JSONP_Util.testKeyDoubleValue(parser, "expPositive4", (double) 9E+3); + JSONP_Util.testKeyDoubleValue(parser, "expNegative1", (double) 7e-3); + JSONP_Util.testKeyDoubleValue(parser, "expNegative2", (double) 7E-3); + JSONP_Util.testKeyStringValue(parser, "asciiChars", + JSONP_Data.asciiCharacters); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } catch (Exception e) { + throw e; + } + return pass; + } + + /* + * Utitity method to parse JsonObjectWithLotsOfNestedObjectsData + */ + private boolean parseAndVerify_JsonObjectWithLotsOfNestedObjectsData( + JsonParser parser) throws Exception { + boolean pass = true; + + try { + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + for (int i = 1; i < 31; i++) { + JSONP_Util.testKeyStartObjectValue(parser, "nested" + i); + JSONP_Util.testKeyStringValue(parser, "name" + i, "value" + i); + } + for (int i = 1; i < 31; i++) { + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + } + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } catch (Exception e) { + throw e; + } + return pass; + } + + /* + * Utitity method to parse JsonArrayWithLotsOfNestedObjectsData + */ + private boolean parseAndVerify_JsonArrayWithLotsOfNestedObjectsData( + JsonParser parser) throws Exception { + boolean pass = true; + + try { + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser, "name1", "value1"); + for (int i = 2; i < 31; i++) { + JSONP_Util.testKeyStartObjectValue(parser, "nested" + i); + JSONP_Util.testKeyStringValue(parser, "name" + i, "value" + i); + } + for (int i = 2; i < 31; i++) { + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + } + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } catch (Exception e) { + throw e; + } + return pass; + } + + /* + * Utitity method to parse JsonArrayWithLotsOfNestedArraysData + */ + private boolean parseAndVerify_JsonArrayWithLotsOfNestedArraysData( + JsonParser parser) throws Exception { + boolean pass = true; + + try { + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser, "name1"); + JSONP_Util.testStringValue(parser, "value1"); + for (int i = 2; i < 31; i++) { + JSONP_Util.testStringValue(parser, "nested" + i); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser, "name" + i); + JSONP_Util.testStringValue(parser, "value" + i); + } + for (int i = 2; i < 31; i++) { + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + } + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } catch (Exception e) { + throw e; + } + return pass; + } + + /* + * Utitity method to parse JsonArrayWithMultipleArraysData + */ + private boolean parseAndVerify_JsonArrayWithMultipleArraysData( + JsonParser parser) throws Exception { + boolean pass = true; + + try { + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser, "string"); + JSONP_Util.testIntegerValue(parser, 100); + JSONP_Util.testTrueValue(parser, JsonParser.Event.VALUE_TRUE); + JSONP_Util.testFalseValue(parser, JsonParser.Event.VALUE_FALSE); + JSONP_Util.testNullValue(parser, JsonParser.Event.VALUE_NULL); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser, "object", "object"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser, "one"); + JSONP_Util.testStringValue(parser, "two"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testIntegerValue(parser, 100); + JSONP_Util.testDoubleValue(parser, (double) 7e7); + JSONP_Util.testTrueValue(parser, JsonParser.Event.VALUE_TRUE); + JSONP_Util.testFalseValue(parser, JsonParser.Event.VALUE_FALSE); + JSONP_Util.testNullValue(parser, JsonParser.Event.VALUE_NULL); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser, "object2", "object2"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } catch (Exception e) { + throw e; + } + return pass; + } + + /* + * Utitity method to parse JsonArrayWithAllTypesOfData + */ + private boolean parseAndVerify_JsonArrayWithAllTypesOfData(JsonParser parser) + throws Exception { + boolean pass = true; + + try { + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser, ""); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testStringValue(parser, "string"); + JSONP_Util.testIntegerValue(parser, 100); + JSONP_Util.testTrueValue(parser, JsonParser.Event.VALUE_TRUE); + JSONP_Util.testFalseValue(parser, JsonParser.Event.VALUE_FALSE); + JSONP_Util.testNullValue(parser, JsonParser.Event.VALUE_NULL); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser, "emptyString", ""); + JSONP_Util.testKeyStartArrayValue(parser, "emptyArray"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testKeyStartObjectValue(parser, "emptyObject"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testKeyStringValue(parser, "string", "string"); + JSONP_Util.testKeyIntegerValue(parser, "number", 100); + JSONP_Util.testKeyTrueValue(parser, "true"); + JSONP_Util.testKeyFalseValue(parser, "false"); + JSONP_Util.testKeyNullValue(parser, "null"); + JSONP_Util.testKeyStartObjectValue(parser, "object"); + JSONP_Util.testKeyStringValue(parser, "name", "value"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testKeyStartArrayValue(parser, "array"); + JSONP_Util.testStringValue(parser, "one"); + JSONP_Util.testStringValue(parser, "two"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser, "string"); + JSONP_Util.testIntegerValue(parser, 100); + JSONP_Util.testTrueValue(parser, JsonParser.Event.VALUE_TRUE); + JSONP_Util.testFalseValue(parser, JsonParser.Event.VALUE_FALSE); + JSONP_Util.testNullValue(parser, JsonParser.Event.VALUE_NULL); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStringValue(parser, "name", "value"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.testEventType(parser, JsonParser.Event.START_ARRAY); + JSONP_Util.testStringValue(parser, "one"); + JSONP_Util.testStringValue(parser, "two"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.testIntegerValue(parser, 100); + JSONP_Util.testIntegerValue(parser, -100); + JSONP_Util.testLongValue(parser, 9223372036854775807L); + JSONP_Util.testLongValue(parser, -9223372036854775808L); + JSONP_Util.testDoubleValue(parser, (double) 0.5); + JSONP_Util.testDoubleValue(parser, (double) -0.5); + JSONP_Util.testDoubleValue(parser, (double) 7e3); + JSONP_Util.testDoubleValue(parser, (double) 7e+3); + JSONP_Util.testDoubleValue(parser, (double) 9E3); + JSONP_Util.testDoubleValue(parser, (double) 9E+3); + JSONP_Util.testDoubleValue(parser, (double) 7e-3); + JSONP_Util.testDoubleValue(parser, (double) 7E-3); + JSONP_Util.testStringValue(parser, JSONP_Data.asciiCharacters); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } catch (Exception e) { + throw e; + } + return pass; + } + + private boolean parseAndVerify_JsonHelloWorld(JsonParser parser) + throws Exception { + boolean pass = true; + + try { + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyStartObjectValue(parser, "greetingObj"); + JSONP_Util.dumpLocation(parser); + JSONP_Util.testKeyStringValue(parser, "hello", "world"); + JSONP_Util.dumpLocation(parser); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.dumpLocation(parser); + JSONP_Util.testKeyStartArrayValue(parser, "greetingArr"); + JSONP_Util.dumpLocation(parser); + JSONP_Util.testStringValue(parser, "hello"); + JSONP_Util.dumpLocation(parser); + JSONP_Util.testStringValue(parser, "world"); + JSONP_Util.dumpLocation(parser); + JSONP_Util.testEventType(parser, JsonParser.Event.END_ARRAY); + JSONP_Util.dumpLocation(parser); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + JSONP_Util.dumpLocation(parser); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + } catch (Exception e) { + throw e; + } + return pass; + } + + /* Tests */ + + /* + * @testName: jsonParserTest1 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:120; JSONP:JAVADOC:122; + * JSONP:JAVADOC:133; JSONP:JAVADOC:235; JSONP:JAVADOC:237; JSONP:JAVADOC:239; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonObject defined in "JSONP_Data.jsonObjectWithAllTypesOfData". Creates + * the JsonParser via the API: + * + * JsonParser parser = Json.createParser(Reader) + */ + @Test + public void jsonParserTest1() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println("-------------------------------------"); + System.out.println("TEST CASE [Json.createParser(Reader)]"); + System.out.println("-------------------------------------"); + System.out.println("Create Reader from (JSONP_Data.jsonObjectWithAllTypesOfData)"); + StringReader reader = new StringReader( + JSONP_Data.jsonObjectWithAllTypesOfData); + System.out.println("Create JsonParser from the Reader"); + parser = Json.createParser(reader); + System.out.println( + "Verify that JSON Parser Events/Data matches (JSONP_Data.jsonObjectWithAllTypesOfData)"); + pass = parseAndVerify_JsonObjectWithAllTypesOfData(parser); + } catch (Exception e) { + throw new Fault("jsonParserTest1 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest1 Failed"); + } + + /* + * @testName: jsonParserTest2 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:120; JSONP:JAVADOC:122; + * JSONP:JAVADOC:417; JSONP:JAVADOC:235; JSONP:JAVADOC:237; JSONP:JAVADOC:239; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; JSONP:JAVADOC:166; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonObject defined in "JSONP_Data.jsonObjectWithAllTypesOfData". Creates + * the JsonParser via the API: + * + * JsonParser parser = + * Json.createParserFactory(Map<String,?>).createParser(JsonObject) + */ + @Test + public void jsonParserTest2() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "----------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(JsonObject)]"); + System.out.println( + "----------------------------------------------------------------------------"); + System.out.println( + "Create JsonObject from (JSONP_Data.jsonObjectWithAllTypesOfData)"); + JsonObject jsonObj = JSONP_Util + .createJsonObjectFromString(JSONP_Data.jsonObjectWithAllTypesOfData); + JSONP_Util.dumpJsonObject(jsonObj); + System.out.println("Create JsonParser from the JsonObject"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(jsonObj); + System.out.println("parser=" + parser); + System.out.println( + "Verify that JSON Parser Events/Data matches (JSONP_Data.jsonObjectWithAllTypesOfData)"); + pass = parseAndVerify_JsonObjectWithAllTypesOfData(parser); + } catch (Exception e) { + throw new Fault("jsonParserTest2 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest2 Failed"); + } + + /* + * @testName: jsonParserTest3 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:122; JSONP:JAVADOC:133; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonObject defined in "JSONP_Data.jsonObjectWithLotsOfNestedObjectsData". + * Creates the JsonParser via the API: + * + * JsonParser parser = Json.createParser(Reader) + */ + @Test + public void jsonParserTest3() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println("-------------------------------------------"); + System.out.println("TEST CASE [Json.createParser(Reader) again]"); + System.out.println("-------------------------------------------"); + System.out.println( + "Create Reader from (JSONP_Data.jsonObjectWithLotsOfNestedObjectsData)"); + StringReader reader = new StringReader( + JSONP_Data.jsonObjectWithLotsOfNestedObjectsData); + System.out.println("Create JsonParser from the Reader"); + parser = Json.createParser(reader); + System.out.println( + "Verify that JSON Parser Events/Data matches (JSONP_Data.jsonObjectWithLotsOfNestedObjectsData)"); + pass = parseAndVerify_JsonObjectWithLotsOfNestedObjectsData(parser); + } catch (Exception e) { + throw new Fault("jsonParserTest3 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest3 Failed"); + } + + /* + * @testName: jsonParserTest4 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:122; JSONP:JAVADOC:417; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; JSONP:JAVADOC:166; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonObject defined in "JSONP_Data.jsonObjectithLotsOfNestedObjectsData". + * Creates the JsonParser via the API: + * + * JsonParser parser = + * Json.createParserFactory(Map<String,?>).createParser(JsonObject) + */ + @Test + public void jsonParserTest4() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "-----------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(JsonObject object) again]"); + System.out.println( + "-----------------------------------------------------------------------------------------"); + System.out.println( + "Create JsonObject from (JSONP_Data.jsonObjectWithLotsOfNestedObjectsData)"); + JsonObject jsonObj = JSONP_Util.createJsonObjectFromString( + JSONP_Data.jsonObjectWithLotsOfNestedObjectsData); + JSONP_Util.dumpJsonObject(jsonObj); + System.out.println("Create JsonParser from the JsonObject"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(jsonObj); + System.out.println( + "Verify that JSON Parser Events/Data matches (JSONP_Data.jsonObjectWithLotsOfNestedObjectsData)"); + pass = parseAndVerify_JsonObjectWithLotsOfNestedObjectsData(parser); + } catch (Exception e) { + throw new Fault("jsonParserTest4 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest4 Failed"); + } + + /* + * @testName: jsonParserTest5 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:120; JSONP:JAVADOC:122; + * JSONP:JAVADOC:417; JSONP:JAVADOC:235; JSONP:JAVADOC:237; JSONP:JAVADOC:239; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; JSONP:JAVADOC:167; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonArray defined in "JSONP_Data.jsonArrayWithMultipleArraysData". Creates + * the JsonParser via the API: + * + * JsonParser parser = + * Json.createParserFactory(Map<String,?>).createParser(JsonArray) + */ + @Test + public void jsonParserTest5() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "---------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(JsonArray)]"); + System.out.println( + "---------------------------------------------------------------------------"); + System.out.println( + "Create JsonArray from (JSONP_Data.jsonArrayWithMultipleArraysData)"); + JsonArray jsonArr = JSONP_Util.createJsonArrayFromString( + JSONP_Data.jsonArrayWithMultipleArraysData); + JSONP_Util.dumpJsonArray(jsonArr); + System.out.println("Create JsonParser from the JsonArray"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(jsonArr); + System.out.println( + "Verify that JSON Parser Events/Data matches (JSONP_Data.jsonArrayWithMultipleArraysData)"); + pass = parseAndVerify_JsonArrayWithMultipleArraysData(parser); + } catch (Exception e) { + throw new Fault("jsonParserTest5 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest5 Failed"); + } + + /* + * @testName: jsonParserTest6 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:120; JSONP:JAVADOC:122; + * JSONP:JAVADOC:172; JSONP:JAVADOC:235; JSONP:JAVADOC:237; JSONP:JAVADOC:239; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonArray defined in resource file "jsonArrayWithAllTypesOfData.json". + * + * Creates the JsonParser via the API: + * + * JsonParser parser = Json.createParser(InputStream) + */ + @Test + public void jsonParserTest6() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println("------------------------------------------"); + System.out.println("TEST CASE [Json.createParser(InputStream)]"); + System.out.println("------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonArrayWithAllTypesOfData.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonArrayWithAllTypesOfData.json"); + System.out.println("Create JsonParser from the InputStream"); + parser = Json.createParser(istream); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonArrayWithAllTypesOfData.json)"); + pass = parseAndVerify_JsonArrayWithAllTypesOfData(parser); + } catch (Exception e) { + throw new Fault("jsonParserTest6 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest6 Failed"); + } + + /* + * @testName: jsonParserTest7 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:120; JSONP:JAVADOC:122; + * JSONP:JAVADOC:417; JSONP:JAVADOC:164; JSONP:JAVADOC:235; JSONP:JAVADOC:237; + * JSONP:JAVADOC:239; JSONP:JAVADOC:375; JSONP:JAVADOC:376; + * + * @test_Strategy: Tests the JsonParser parser with a configuration. Verifies + * PARSING of the JsonObject defined in + * "JSONP_Data.jsonObjectWithAllTypesOfData". Creates the JsonParser via the + * following API + * + * JsonParser parser = Json.createParserFactory(Map<String, + * ?>).createParser(Reader) + */ + @Test + public void jsonParserTest7() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "-------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String, ?>).createParser(Reader)]"); + System.out.println( + "-------------------------------------------------------------------------"); + System.out.println("Create a Reader from (JSONP_Data.jsonObjectWithAllTypesOfData)"); + StringReader reader = new StringReader( + JSONP_Data.jsonObjectWithAllTypesOfData); + System.out.println("Create JsonParser using Reader and a configuration"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(reader); + System.out.println("Call JsonParser.toString() to print the JsonObject"); + parser.toString(); + System.out.println( + "Verify that JSON Parser Events/Data matches (JSONP_Data.jsonObjectWithAllTypesOfData)"); + if (!parseAndVerify_JsonObjectWithAllTypesOfData(parser)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonParserTest7 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest7 Failed"); + } + + /* + * @testName: jsonParserTest8 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:122; JSONP:JAVADOC:417; + * JSONP:JAVADOC:167; JSONP:JAVADOC:375; JSONP:JAVADOC:376; + * + * @test_Strategy: Tests the JsonParser parser with a configuration. Verifies + * PARSING of the JsonArray defined in + * "JSONP_Data.jsonArrayWithLotsOfNestedObjectsData". Creates the JsonParser + * via the following API + * + * JsonParser parser = Json.createParserFactory(Map<String, + * ?>).createParser(JsonArray) + */ + @Test + public void jsonParserTest8() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "----------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String, ?>).createParser(JsonArray)]"); + System.out.println( + "----------------------------------------------------------------------------"); + System.out.println( + "Create a JsonArray from (JSONP_Data.jsonArrayWithLotsOfNestedObjectsData)"); + JsonArray jsonArr = JSONP_Util.createJsonArrayFromString( + JSONP_Data.jsonArrayWithLotsOfNestedObjectsData); + JSONP_Util.dumpJsonArray(jsonArr); + System.out.println("Create JsonParser using JsonArray and a configuration"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(jsonArr); + System.out.println("Call JsonParser.toString() to print the JsonObject"); + parser.toString(); + System.out.println( + "Verify that JSON Parser Events/Data matches (JSONP_Data.jsonArrayWithLotsOfNestedObjectsData)"); + if (!parseAndVerify_JsonArrayWithLotsOfNestedObjectsData(parser)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonParserTest8 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest8 Failed"); + } + + /* + * @testName: jsonParserTest9 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:120; JSONP:JAVADOC:122; + * JSONP:JAVADOC:417; JSONP:JAVADOC:167; JSONP:JAVADOC:235; JSONP:JAVADOC:237; + * JSONP:JAVADOC:239; JSONP:JAVADOC:375; JSONP:JAVADOC:376; + * + * @test_Strategy: Tests the JsonParser parser with an empty configuration. + * Verifies PARSING of the JsonArray defined in + * "JSONP_Data.jsonArrayWithMultipleArraysData". Creates the JsonParser via + * the following API + * + * JsonParser parser = Json.createParserFactory(Map<String, + * ?>).createParser(JsonArray) + */ + @Test + public void jsonParserTest9() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "----------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String, ?>).createParser(JsonArray)]"); + System.out.println( + "----------------------------------------------------------------------------"); + System.out.println( + "Create JsonArray from (JSONP_Data.jsonArrayWithMultipleArraysData)"); + JsonArray jsonArr = JSONP_Util.createJsonArrayFromString( + JSONP_Data.jsonArrayWithMultipleArraysData); + JSONP_Util.dumpJsonArray(jsonArr); + System.out.println("Create JsonParser using JsonArray and a configuration"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(jsonArr); + System.out.println("Call JsonParser.toString() to print the JsonArray"); + parser.toString(); + System.out.println( + "Verify that JSON Parser Events/Data matches (JSONP_Data.jsonArrayWithMultipleArraysData)"); + if (!parseAndVerify_JsonArrayWithMultipleArraysData(parser)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonParserTest9 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest9 Failed"); + } + + /* + * @testName: jsonParserTest10 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:122; JSONP:JAVADOC:417; + * JSONP:JAVADOC:165; JSONP:JAVADOC:375; JSONP:JAVADOC:376; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonObject defined in resource file + * "jsonObjectWithLotsOfNestedObjectsData.json". Creates the JsonParser via + * the following API + * + * JsonParser parser = Json.createParserFactory(Map<String, + * ?>).createParser(InputStream) + */ + @Test + public void jsonParserTest10() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String, ?>).createParser(InputStream)]"); + System.out.println( + "------------------------------------------------------------------------------"); + System.out.println("Create JsonParser using InputStream and a configuration"); + InputStream istream = JSONP_Util.getInputStreamFromResource( + "jsonObjectWithLotsOfNestedObjectsData.json"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream); + System.out.println("Call JsonParser.toString() to print the JsonObject"); + parser.toString(); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectWithLotsOfNestedObjectsData.json)"); + if (!parseAndVerify_JsonObjectWithLotsOfNestedObjectsData(parser)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonParserTest10 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest10 Failed"); + } + + /* + * @testName: jsonParserTest11 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:120; JSONP:JAVADOC:122; + * JSONP:JAVADOC:235; JSONP:JAVADOC:237; JSONP:JAVADOC:239; JSONP:JAVADOC:375; + * JSONP:JAVADOC:376; JSONP:JAVADOC:417; JSONP:JAVADOC:201; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonArray defined in resource file + * "jsonArrayWithAllTypesOfDataUTF16BE.json". Use UTF-16BE encoding. + * + * Creates the JsonParser via the API: + * + * JsonParser parser = + * Json.createParserFactory(Map<String,?>).createParser(InputStream, Charset) + */ + @Test + public void jsonParserTest11() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "--------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(InputStream, Charset)]"); + System.out.println( + "--------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonArrayWithAllTypesOfDataUTF16BE.json)"); + InputStream istream = JSONP_Util.getInputStreamFromResource( + "jsonArrayWithAllTypesOfDataUTF16BE.json"); + System.out.println( + "Create JsonParser from the InputStream with character encoding UTF-16BE"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream, JSONP_Util.UTF_16BE); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonArrayWithAllTypesOfDataUTF16BE.json)"); + pass = parseAndVerify_JsonArrayWithAllTypesOfData(parser); + } catch (Exception e) { + throw new Fault("jsonParserTest11 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest11 Failed"); + } + + /* + * @testName: jsonParserTest12 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:122; JSONP:JAVADOC:417; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; JSONP:JAVADOC:201; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonArray defined in resource file + * "jsonArrayWithLotsOfNestedArraysData.json". Use UTF-8 encoding. + * + * Creates the JsonParser via the API: + * + * JsonParser parser = Json.createParserFactory(Map<String, + * ?>).createParser(InputStream, Charset) + */ + @Test + public void jsonParserTest12() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "---------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String, ?>).createParser(InputStream, Charset)]"); + System.out.println( + "---------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonArrayWithLotsOfNestedArraysData.json)"); + InputStream istream = JSONP_Util.getInputStreamFromResource( + "jsonArrayWithLotsOfNestedArraysData.json"); + System.out.println( + "Create JsonParser from the InputStream with character encoding UTF-8 and a configuration"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream, JSONP_Util.UTF_8); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonArrayWithLotsOfNestedArraysData.json)"); + if (!parseAndVerify_JsonArrayWithLotsOfNestedArraysData(parser)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonParserTest12 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest12 Failed"); + } + + /* + * @testName: jsonParserTest13 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:120; JSONP:JAVADOC:122; + * JSONP:JAVADOC:201; JSONP:JAVADOC:235; JSONP:JAVADOC:237; JSONP:JAVADOC:239; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonObject defined in UTF-16LE encoding resource file + * "jsonObjectWithAllTypesOfDataUTF16LE.json". + * + * Creates the JsonParser via the API: + * + * JsonParser parser = Json.createParserFactory(Map<String, + * ?>).createParser(InputStream, Charset) + */ + @Test + public void jsonParserTest13() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "---------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String, ?>).createParser(InputStream, Charset)]"); + System.out.println( + "---------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectWithAllTypesOfDataUTF16LE.json)"); + InputStream istream = JSONP_Util.getInputStreamFromResource( + "jsonObjectWithAllTypesOfDataUTF16LE.json"); + System.out.println("Create JsonParser from the InputStream using UTF-16LE encoding"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream, JSONP_Util.UTF_16LE); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectWithAllTypesOfDataUTF16LE.json)"); + pass = parseAndVerify_JsonObjectWithAllTypesOfData(parser); + } catch (Exception e) { + throw new Fault("jsonParserTest13 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest13 Failed"); + } + + /* + * @testName: jsonParserTest14 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:122; JSONP:JAVADOC:172; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; JSONP:JAVADOC:477; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonObject defined in resource file "jsonHelloWorld.json.json". + * + * Creates the JsonParser via the API: + * + * JsonParser parser = Json.createParser(InputStream) + */ + @Test + public void jsonParserTest14() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println("------------------------------------------"); + System.out.println("TEST CASE [Json.createParser(InputStream)]"); + System.out.println("------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonHelloWorld.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonHelloWorld.json"); + System.out.println("Create JsonParser from the InputStream"); + parser = Json.createParser(istream); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonHelloWorld.json)"); + pass = parseAndVerify_JsonHelloWorld(parser); + } catch (Exception e) { + throw new Fault("jsonParserTest14 Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("jsonParserTest14 Failed"); + } + + /* + * @testName: parseUTFEncodedTests + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:122; JSONP:JAVADOC:417; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; JSONP:JAVADOC:201; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonObject defined in resource files: + * + * jsonObjectEncodingUTF8.json jsonObjectEncodingUTF16.json + * jsonObjectEncodingUTF16LE.json jsonObjectEncodingUTF16BE.json + * jsonObjectEncodingUTF32LE.json jsonObjectEncodingUTF32BE.json + * + * Creates the JsonParser via the API: + * + * JsonParser parser = + * Json.createParserFactory(Map<String,?>).createParser(InputStream, Charset) + * + * For each supported encoding supported by JSON RFC parse the JsonObject and + * verify we get the expected results. The Charset encoding is passed in as an + * argument for each encoding type tested. + */ + @Test + public void parseUTFEncodedTests() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "-----------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(InputStream, Charset) as UTF-8]"); + System.out.println( + "-----------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF8.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF8.json"); + System.out.println( + "Create JsonParser from the InputStream with character encoding UTF-8"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream, JSONP_Util.UTF_8); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF8.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-8 encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(InputStream, Charset) as UTF-16]"); + System.out.println( + "------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16.json"); + System.out.println( + "Create JsonParser from the InputStream with character encoding UTF-16"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream, JSONP_Util.UTF_16); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF16.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-16 encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(InputStream, Charset) as UTF-16LE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16LE.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16LE.json"); + System.out.println( + "Create JsonParser from the InputStream with character encoding UTF-16LE"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream, JSONP_Util.UTF_16LE); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF16LE.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-16LE encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(InputStream, Charset) as UTF-16BE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16BE.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16BE.json"); + System.out.println( + "Create JsonParser from the InputStream with character encoding UTF-16BE"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream, JSONP_Util.UTF_16BE); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF16BE.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-16BE encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(InputStream, Charset) as UTF-32LE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF32LE.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF32LE.json"); + System.out.println( + "Create JsonParser from the InputStream with character encoding UTF-32LE"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream, JSONP_Util.UTF_32LE); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF32LE.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-32LE encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "-------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParserFactory(Map<String,?>).createParser(InputStream, Charset) as UTF-32BE]"); + System.out.println( + "-------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF32BE.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF32BE.json"); + System.out.println( + "Create JsonParser from the InputStream with character encoding UTF-32BE"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(istream, JSONP_Util.UTF_32BE); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF32BE.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-32BE encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("parseUTFEncodedTests Failed"); + } + + /* + * @testName: parseUTFEncodedTests2 + * + * @assertion_ids: JSONP:JAVADOC:117; JSONP:JAVADOC:120; JSONP:JAVADOC:122; + * JSONP:JAVADOC:172; JSONP:JAVADOC:235; JSONP:JAVADOC:237; JSONP:JAVADOC:239; + * JSONP:JAVADOC:375; JSONP:JAVADOC:376; + * + * @test_Strategy: Tests the JsonParser parser. Verifies PARSING of the + * JsonObject defined in resource files and auto-detecting the encoding: + * + * jsonObjectEncodingUTF8.json jsonObjectEncodingUTF16LE.json + * jsonObjectEncodingUTF16BE.json jsonObjectEncodingUTF32LE.json + * jsonObjectEncodingUTF32BE.json + * + * Creates the JsonParser via the API: + * + * JsonParser parser = Json.createParser(InputStream) + * + * For each supported encoding supported by JSON RFC the above should + * auto-detect the encoding and verify we get the expected results. + */ + @Test + public void parseUTFEncodedTests2() throws Fault { + boolean pass = true; + JsonParser parser = null; + JsonParser.Event event = null; + try { + System.out.println( + "-------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParser(InputStream) and auto-detect as UTF-8]"); + System.out.println( + "-------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF8.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF8.json"); + System.out.println( + "Create JsonParser from the InputStream and auto-detect character encoding UTF-8"); + parser = Json.createParser(istream); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF8.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-8 encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "----------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParser(InputStream) and auto-detect as UTF-16LE]"); + System.out.println( + "----------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16LE.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16LE.json"); + System.out.println( + "Create JsonParser from the InputStream and auto-detect character encoding UTF-16LE"); + parser = Json.createParser(istream); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF16LE.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-16LE encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "----------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParser(InputStream) and auto-detect as UTF-16BE]"); + System.out.println( + "----------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16BE.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16BE.json"); + System.out.println( + "Create JsonParser from the InputStream and auto-detect character encoding UTF-16BE"); + parser = Json.createParser(istream); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF16BE.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-16BE encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "----------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParser(InputStream) and auto-detect as UTF-32LE]"); + System.out.println( + "----------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF32LE.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF32LE.json"); + System.out.println( + "Create JsonParser from the InputStream and auto-detect character encoding UTF-32LE"); + parser = Json.createParser(istream); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF32LE.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-32LE encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "----------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createParser(InputStream) and auto-detect as UTF-32BE]"); + System.out.println( + "----------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF32BE.json)"); + InputStream istream = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF32BE.json"); + System.out.println( + "Create JsonParser from the InputStream and auto-detect character encoding UTF-32BE"); + parser = Json.createParser(istream); + System.out.println( + "Verify that JSON Parser Events/Data matches (jsonObjectEncodingUTF32BE.json)"); + if (!parseAndVerify_JsonObjectUTF(parser)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing parsing of UTF-32BE encoding: " + e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + + if (!pass) + throw new Fault("parseUTFEncodedTests2 Failed"); + } + + /* + * @testName: jsonParserIsIntegralNumberTest + * + * @assertion_ids: JSONP:JAVADOC:120; JSONP:JAVADOC:133; JSONP:JAVADOC:375; + * JSONP:JAVADOC:376; + * + * @test_Strategy: Test JsonParser.isIntegralNumber() method. + */ + @Test + public void jsonParserIsIntegralNumberTest() throws Fault { + boolean pass = true; + JsonParser parser = null; + String jsonTestString = "[123, 12345.45]"; + try { + System.out.println("Create JsonParser"); + parser = Json.createParser(new StringReader(jsonTestString)); + // INTEGRAL NUMBER TEST + JsonParser.Event event = JSONP_Util.getNextSpecificParserEvent(parser, + JsonParser.Event.VALUE_NUMBER); // e=JsonParser.Event.VALUE_NUMBER + JSONP_Util.dumpEventType(event); + if (!JSONP_Util.assertEqualsJsonNumberType(parser.isIntegralNumber(), + JSONP_Util.INTEGRAL)) + pass = false; + else { + if (!JSONP_Util.assertEquals(123, parser.getInt())) + pass = false; + } + // NON_INTEGRAL NUMBER TEST + event = JSONP_Util.getNextSpecificParserEvent(parser, + JsonParser.Event.VALUE_NUMBER); // e=JsonParser.Event.VALUE_NUMBER + JSONP_Util.dumpEventType(event); + if (!JSONP_Util.assertEqualsJsonNumberType(parser.isIntegralNumber(), + JSONP_Util.NON_INTEGRAL)) + pass = false; + else { + if (!JSONP_Util.assertEquals(12345.45, + parser.getBigDecimal().doubleValue())) + pass = false; + } + + } catch (Exception e) { + throw new Fault("jsonParserIsIntegralNumberTest Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + + if (!pass) + throw new Fault("jsonParserIsIntegralNumberTest Failed"); + } + + private boolean tripIllegalStateException(JsonParser parser, + JsonParser.Event event) { + boolean pass = true; + + // Check in case event is null + if (event == null) { + System.err.println("event is null - unexpected."); + return false; + } + System.out.println("Event=" + JSONP_Util.getEventTypeString(event)); + System.out.println("Testing call to JsonParser.getString()"); + if (event != JsonParser.Event.VALUE_STRING + && event != JsonParser.Event.VALUE_NUMBER + && event != JsonParser.Event.KEY_NAME) { + try { + System.out.println("Trip IllegalStateException by calling JsonParser.getString()"); + String string = parser.getString(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + } else { + System.out.println("No testing for IllegalStateException for this scenario."); + } + + System.out.println("Testing call to JsonParser.isIntegralNumber()"); + if (event != JsonParser.Event.VALUE_NUMBER) { + try { + System.out.println( + "Trip IllegalStateException by calling JsonParser.isIntegralNumber()"); + boolean numberType = parser.isIntegralNumber(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + } else { + System.out.println("No testing for IllegalStateException for this scenario."); + } + + System.out.println("Testing call to JsonParser.getBigDecimal()"); + if (event != JsonParser.Event.VALUE_NUMBER) { + try { + System.out.println( + "Trip IllegalStateException by calling JsonParser.getBigDecimal()"); + BigDecimal number = parser.getBigDecimal(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + } else { + System.out.println("No testing for IllegalStateException for this scenario."); + } + + System.out.println("Testing call to JsonParser.getInt()"); + if (event != JsonParser.Event.VALUE_NUMBER) { + try { + System.out.println("Trip IllegalStateException by calling JsonParser.getInt()"); + int number = parser.getInt(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + } else { + System.out.println("No testing for IllegalStateException for this scenario."); + } + + System.out.println("Testing call to JsonParser.getLong()"); + if (event != JsonParser.Event.VALUE_NUMBER) { + try { + System.out.println("Trip IllegalStateException by calling JsonParser.getLong()"); + long number = parser.getLong(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + } else { + System.out.println("No testing for IllegalStateException for this scenario."); + } + return pass; + } + + /* + * @testName: jsonParserIllegalExceptionTests + * + * @assertion_ids: JSONP:JAVADOC:121; JSONP:JAVADOC:123; JSONP:JAVADOC:236; + * JSONP:JAVADOC:238; JSONP:JAVADOC:240; + * + * @test_Strategy: Test JsonParser exception conditions. Trip the following + * exceptions: + * + * java.lang.IllegalStateException + */ + @Test + public void jsonParserIllegalExceptionTests() throws Fault { + boolean pass = true; + JsonParser parser = null; + String jsonTestString = "[\"string\",100,false,null,true,{\"foo\":\"bar\"}]"; + try { + System.out.println("Create JsonParser"); + parser = Json.createParserFactory(JSONP_Util.getEmptyConfig()) + .createParser(new StringReader(jsonTestString)); + JsonParser.Event event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.START_ARRAY */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.VALUE_STRING */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.VALUE_NUMBER */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.VALUE_FALSE */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.VALUE_NULL */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.VALUE_TRUE */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.START_OBJECT */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.KEY_NAME */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.VALUE_STRING */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.END_OBJECT */ + if (!tripIllegalStateException(parser, event)) + pass = false; + event = JSONP_Util + .getNextParserEvent(parser); /* e=JsonParser.Event.END_ARRAY */ + if (!tripIllegalStateException(parser, event)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonParserIllegalExceptionTests Failed: ", e); + } finally { + try { + parser.close(); + } catch (Exception e) { + } + } + + if (!pass) + throw new Fault("jsonParserIllegalExceptionTests Failed"); + } + + /* + * @testName: jsonParserIOErrorTests + * + * @assertion_ids: JSONP:JAVADOC:207; JSONP:JAVADOC:389; JSONP:JAVADOC:415; + * + * @test_Strategy: Tests for JsonException for testable i/o errors. + * + */ + @SuppressWarnings("ConvertToTryWithResources") + @Test + public void jsonParserIOErrorTests() throws Fault { + boolean pass = true; + + String jsonText = "{\"name1\":\"value1\",\"name2\":\"value2\"}"; + + // Trip JsonException if there is an i/o error on + // Json.createParser(InputStream) + try { + System.out.println( + "Trip JsonException if there is an i/o error on Json.createParser(InputStream)."); + System.out.println("Parsing " + jsonText); + InputStream is = JSONP_Util.getInputStreamFromString(jsonText); + MyBufferedInputStream mbi = new MyBufferedInputStream(is, true); + System.out.println("Calling Json.createParser(InputStream)"); + JsonParser parser = Json.createParser(mbi); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonException if there is an i/o error on JsonParser.next() + try { + System.out.println( + "Trip JsonException if there is an i/o error on JsonParser.next()."); + System.out.println("Parsing " + jsonText); + InputStream is = JSONP_Util.getInputStreamFromString(jsonText); + MyBufferedInputStream mbi = new MyBufferedInputStream(is, true); + JsonParser parser = Json.createParser(mbi); + System.out.println("Calling JsonParser.next()"); + parser.next(); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonException if there is an i/o error on JsonParser.close() + try { + System.out.println( + "Trip JsonException if there is an i/o error on JsonParser.close()."); + System.out.println("Parsing " + jsonText); + InputStream is = JSONP_Util.getInputStreamFromString(jsonText); + MyBufferedInputStream mbi = new MyBufferedInputStream(is); + JsonParser parser = Json.createParser(mbi); + mbi.setThrowIOException(true); + System.out.println("Calling JsonParser.close()"); + parser.close(); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonParserIOErrorTests Failed"); + } + + /* + * @testName: jsonParserExceptionTests + * + * @assertion_ids: JSONP:JAVADOC:390; JSONP:JAVADOC:391; + * + * @test_Strategy: Tests for the following exception test cases: + * + * JsonParsingException - if incorrect JSON is encountered while advancing + * parser to next state NoSuchElementException - if there are no more parsing + * states + * + */ + @Test + public void jsonParserExceptionTests() throws Fault { + boolean pass = true; + + // Trip JsonParsingException for JsonParser.next() if incorrect JSON is + // encountered + try { + System.out.println( + "Trip JsonParsingException for JsonParser.next() if incorrect JSON is encountered"); + InputStream is = JSONP_Util.getInputStreamFromString("}{"); + JsonParser parser = Json.createParser(is); + parser.next(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip NoSuchElementException for JsonParser.next() if no more parsing + // states + try { + System.out.println( + "Trip NoSuchElementException for JsonParser.next() if no more parsing states"); + InputStream is = JSONP_Util.getInputStreamFromString("{}"); + JsonParser parser = Json.createParser(is); + parser.next(); // Event -> START_OBJECT { + parser.next(); // Event -> END_OBJECT } + parser.next(); // Event -> NoSuchElementException should be thrown + System.err.println("Did not get expected NoSuchElementException"); + pass = false; + } catch (NoSuchElementException e) { + System.out.println("Caught expected NoSuchElementException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonParserExceptionTests Failed"); + } + + /* + * @testName: invalidLiteralNamesTest + * + * @assertion_ids: JSONP:JAVADOC:133; JSONP:JAVADOC:390; + * + * @test_Strategy: This test trips various JsonParsingException conditions + * when parsing an uppercase literal name that must be lowercase per JSON RFC + * for the literal values (true, false or null). + * + */ + @Test + public void invalidLiteralNamesTest() throws Fault { + boolean pass = true; + + // Trip JsonParsingException for JsonParser.next() if invalid liternal TRUE + // instead of true + try { + System.out.println( + "Trip JsonParsingException for JsonParser.next() if invalid liternal TRUE instead of true."); + System.out.println("Reading " + "[TRUE]"); + JsonParser parser = Json.createParser(new StringReader("[TRUE]")); + parser.next(); // Event -> START_OBJECT { + parser.next(); // Event -> JsonParsingException (invalid literal TRUE) + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonParsingException for JsonParser.next() if invalid liternal FALSE + // instead of false + try { + System.out.println( + "Trip JsonParsingException for JsonParser.next() if invalid liternal FALSE instead of false."); + System.out.println("Reading " + "[FALSE]"); + JsonParser parser = Json.createParser(new StringReader("[FALSE]")); + parser.next(); // Event -> START_OBJECT { + parser.next(); // Event -> JsonParsingException (invalid literal FALSE) + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonParsingException for JsonParser.next() if invalid liternal NULL + // instead of null + try { + System.out.println( + "Trip JsonParsingException for JsonParser.next() if invalid liternal NULL instead of null."); + System.out.println("Reading " + "[NULL]"); + JsonParser parser = Json.createParser(new StringReader("[NULL]")); + parser.next(); // Event -> START_OBJECT { + parser.next(); // Event -> JsonParsingException (invalid literal NULL) + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("invalidLiteralNamesTest Failed"); + } + + /* + * @testName: jsonParser11Test + * + * @assertion_ids: JSONP:JAVADOC:673; JSONP:JAVADOC:674; JSONP:JAVADOC:675; + * JSONP:JAVADOC:676; JSONP:JAVADOC:677; JSONP:JAVADOC:678; JSONP:JAVADOC:679; + * JSONP:JAVADOC:680; JSONP:JAVADOC:583; JSONP:JAVADOC:584; JSONP:JAVADOC:585; + * JSONP:JAVADOC:586; JSONP:JAVADOC:587; JSONP:JAVADOC:588; JSONP:JAVADOC:662; + * JSONP:JAVADOC:663; JSONP:JAVADOC:664; JSONP:JAVADOC:665; JSONP:JAVADOC:666; + * JSONP:JAVADOC:667; + * + * @test_Strategy: Tests JsonParser API methods added in JSON-P 1.1. + */ + @Test + public void jsonParser11Test() throws Fault { + Parser parserTest = new Parser(); + final TestResult result = parserTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparsertests/Parser.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparsertests/Parser.java new file mode 100644 index 0000000..3e5e988 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonparsertests/Parser.java
@@ -0,0 +1,670 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonparsertests; + +import jakarta.jsonp.tck.api.common.TestResult; +import java.io.StringReader; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonParser; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests: {@link JsonParser} API + * methods added in JSON-P 1.1. + */ +public class Parser { + + /** Tests input data with various JsonValue instances. */ + private static final JsonValue[] VALUES = new JsonValue[] { + toJsonValue(STR_VALUE), // Non JsonObject with String + toJsonValue(INT_VALUE), // Non JsonObject with int + toJsonValue(LNG_VALUE), // Non JsonObject with long + toJsonValue(DBL_VALUE), // Non JsonObject with double + toJsonValue(BOOL_VALUE), // Non JsonObject with boolean + toJsonValue(BDC_VALUE), // Non JsonObject with BigDecimal + toJsonValue(BIN_VALUE), // Non JsonObject with BigInteger + createSimpleObjectStr(), // JsonObject with String + createSimpleObjectInt(), // JsonObject with int + createSimpleObjectBool(), // JsonObject with boolean + createSimpleObjectObject(), // JsonObject with JsonObject + createEmptyArrayWithStr(), // JsonArray with String + createEmptyArrayWithInt(), // JsonArray with int + createEmptyArrayWithBool(), // JsonArray with boolean + createEmptyArrayWithObject() // JsonArray with JsonObject + }; + + // /** Tests input data with simple JsonValue instances. */ + // private static final JsonValue[] SIMPLE_VALUES = new JsonValue[] { + // toJsonValue(STR_VALUE), // Non JsonObject with String + // toJsonValue(INT_VALUE), // Non JsonObject with int + // toJsonValue(LNG_VALUE), // Non JsonObject with long + // toJsonValue(BOOL_VALUE), // Non JsonObject with boolean + // toJsonValue(BDC_VALUE), // Non JsonObject with BigDecimal + // toJsonValue(BIN_VALUE) // Non JsonObject with BigInteger + // }; + + /** Tests input data with compound JsonValue instances (object or array). */ + private static final JsonStructure[] COMPOUND_VALUES = new JsonStructure[] { + createSimpleObjectStr(), // JsonObject with String + createSimpleObjectInt(), // JsonObject with int + createSimpleObjectBool(), // JsonObject with boolean + createSimpleObjectObject(), // JsonObject with JsonObject + createEmptyArrayWithStr(), // JsonArray with String + createEmptyArrayWithInt(), // JsonArray with int + createEmptyArrayWithBool(), // JsonArray with boolean + createEmptyArrayWithObject() // JsonArray with JsonObject + }; + + /** Tests input data with empty JsonObject and JsonArray instances. */ + private static final JsonStructure[] EMPTY_VALUES = new JsonStructure[] { + createEmptyObject(), // Empty JsonObject + createEmptyArray() // Empty JsonArray + }; + + /** Tests input data with JsonObject instances. */ + private static final JsonObject[] OBJ_VALUES = new JsonObject[] { + createSimpleObjectStr(), // JsonObject with String + createSimpleObjectInt(), // JsonObject with int + createSimpleObjectBool(), // JsonObject with boolean + createSimpleObjectObject(), // JsonObject with JsonObject + createSimpleObjectWithStr() // JsonObject with default value (String) and + // another String + + }; + + /** Tests input data with non JsonObject instances. */ + private static final JsonValue[] NON_OBJ_VALUES = new JsonValue[] { + toJsonValue(STR_VALUE), // Non JsonObject with String + toJsonValue(INT_VALUE), // Non JsonObject with int + toJsonValue(LNG_VALUE), // Non JsonObject with long + toJsonValue(DBL_VALUE), // Non JsonObject with double + toJsonValue(BOOL_VALUE), // Non JsonObject with boolean + toJsonValue(BDC_VALUE), // Non JsonObject with BigDecimal + toJsonValue(BIN_VALUE), // Non JsonObject with BigInteger + createEmptyArrayWithStr(), // JsonArray with String + createEmptyArrayWithInt(), // JsonArray with int + createEmptyArrayWithBool(), // JsonArray with boolean + createEmptyArrayWithObject() // JsonArray with JsonObject + }; + + /** Tests input data with JsonArray instances. */ + private static final JsonArray[] ARRAY_VALUES = new JsonArray[] { + createEmptyArrayWithStr(), // JsonArray with String + createEmptyArrayWithInt(), // JsonArray with int + createEmptyArrayWithBool(), // JsonArray with boolean + createEmptyArrayWithObject() // JsonArray with JsonObject + }; + + /** Tests input data with non JsonArray instances. */ + private static final JsonValue[] NON_ARRAY_VALUES = new JsonValue[] { + toJsonValue(STR_VALUE), // Non JsonObject with String + toJsonValue(INT_VALUE), // Non JsonObject with int + toJsonValue(LNG_VALUE), // Non JsonObject with long + toJsonValue(DBL_VALUE), // Non JsonObject with double + toJsonValue(BOOL_VALUE), // Non JsonObject with boolean + toJsonValue(BDC_VALUE), // Non JsonObject with BigDecimal + toJsonValue(BIN_VALUE), // Non JsonObject with BigInteger + createSimpleObjectStr(), // JsonObject with String + createSimpleObjectInt(), // JsonObject with int + createSimpleObjectBool(), // JsonObject with boolean + createSimpleObjectObject() // JsonObject with JsonObject + }; + + /** + * Creates an instance of {@link JsonParser} API methods added in JSON-P 1.1 + * test. + */ + Parser() { + super(); + } + + /** + * Test {@link JsonParser} API methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonParser API methods added in JSON-P 1.1."); + System.out.println("JsonParser API methods added in JSON-P 1.1."); + testGetObject(result); + testGetNonObject(result); + testGetArray(result); + testGetNonArray(result); + testGetValue(result); + testGetIllegalValue(result); + testGetObjectStream(result); + testGetNonObjectStream(result); + testGetArrayStream(result); + testGetNonArrayStream(result); + testGetValueStream(result); + testGetCompoundValueStream(result); + testSkipArray(result); + testSkipNonArray(result); + testSkipObject(result); + testSkipNonObject(result); + return result; + } + + /** + * Test {@code JsonParser getObject()} method on JSON object values. + */ + private void testGetObject(final TestResult result) { + for (JsonObject value : OBJ_VALUES) { + final String data = jsonData(value); + System.out.println(" - getObject() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + JsonObject out = parser.getObject(); + if (operationFailed(value, out)) { + result.fail("getObject()", "Output value " + valueToString(out) + + " shall be " + valueToString(value)); + } + } catch (JsonException ex) { + System.out.println("Caught JsonException: " + ex.getLocalizedMessage()); + result.fail("getObject()", + "Caught JsonException: " + ex.getLocalizedMessage()); + } + } + } + + /** + * Test {@code JsonParser getObject()} method on non JSON object values. + */ + private void testGetNonObject(final TestResult result) { + for (JsonValue value : NON_OBJ_VALUES) { + final String data = jsonData(value); + System.out.println(" - getObject() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + parser.getObject(); + result.fail("getObject()", + "Calling method on non object value shall throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println(" Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("getObject()", + "Calling method on non object value shall throw IllegalStateException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonParser getArray()} method on JSON array values. + */ + private void testGetArray(final TestResult result) { + for (JsonArray value : ARRAY_VALUES) { + final String data = jsonData(value); + System.out.println(" - getArray() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + JsonArray out = parser.getArray(); + if (operationFailed(value, out)) { + result.fail("getArray()", "Output value " + valueToString(out) + + " shall be " + valueToString(value)); + } + } catch (JsonException ex) { + System.out.println("Caught JsonException: " + ex.getLocalizedMessage()); + result.fail("getArray()", + "Caught JsonException: " + ex.getLocalizedMessage()); + } + } + } + + /** + * Test {@code JsonParser getArray()} method on non JSON object values. + */ + private void testGetNonArray(final TestResult result) { + for (JsonValue value : NON_ARRAY_VALUES) { + final String data = jsonData(value); + System.out.println(" - getArray() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + parser.getArray(); + result.fail("getArray()", + "Calling method on non array value shall throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println(" Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("getArray()", + "Calling method on non array value shall throw IllegalStateException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonParser getValue()} method on common JSON values. + */ + private void testGetValue(final TestResult result) { + for (JsonValue value : VALUES) { + final String data = jsonData(value); + System.out.println(" - getValue() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + JsonValue out = parser.getValue(); + if (operationFailed(value, out)) { + result.fail("getValue()", "Output value " + valueToString(out) + + " shall be " + valueToString(value)); + } + } catch (JsonException ex) { + System.out.println("Caught JsonException: " + ex.getLocalizedMessage()); + result.fail("getValue()", + "Caught JsonException: " + ex.getLocalizedMessage()); + } + } + } + + /** + * Test {@code JsonParser getValue()} method on END_OBJECT and END_ARRAY + * lexical elements. + */ + private void testGetIllegalValue(final TestResult result) { + for (JsonValue value : EMPTY_VALUES) { + final String data = jsonData(value); + System.out.println(" - getValue() on 2nd lexical element of " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); // Skip to START ELEMENT + parser.next(); // Skip to END ELEMENT + parser.getValue(); + result.fail("getValue()", + "Calling method on END_OBJECT and END_ARRAY lexical elements shall throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println(" Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("getValue()", + "Calling method on END_OBJECT and END_ARRAY lexical elements shall throw IllegalStateException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonParser getObjectStream()} method on JSON object values. + */ + private void testGetObjectStream(final TestResult result) { + for (JsonObject value : OBJ_VALUES) { + final String data = jsonData(value); + System.out.println(" - getObjectStream() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + Stream<Map.Entry<String, JsonValue>> out = parser.getObjectStream(); + if (operationFailed(value, out)) { + result.fail("getObjectStream()", + "Output Stream shall contain " + valueToString(value)); + } + } catch (JsonException ex) { + System.out.println("Caught JsonException: " + ex.getLocalizedMessage()); + result.fail("getObjectStream()", + "Caught JsonException: " + ex.getLocalizedMessage()); + } + } + } + + /** + * Test {@code JsonParser getObjectStream()} method on non JSON object values. + */ + private void testGetNonObjectStream(final TestResult result) { + for (JsonValue value : NON_OBJ_VALUES) { + final String data = jsonData(value); + System.out.println(" - getObjectStream() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + parser.getObjectStream(); + result.fail("getObjectStream()", + "Calling method on non object value shall throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println(" Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("getObjectStream()", + "Calling method on non object value shall throw IllegalStateException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonParser getArrayStream()} method on JSON array values. + */ + private void testGetArrayStream(final TestResult result) { + for (JsonArray value : ARRAY_VALUES) { + final String data = jsonData(value); + System.out.println(" - getArrayStream() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + Stream<JsonValue> out = parser.getArrayStream(); + if (operationFailed(value, out)) { + result.fail("getArrayStream()", + "Output Stream shall contain " + valueToString(value)); + } + } catch (JsonException ex) { + System.out.println("Caught JsonException: " + ex.getLocalizedMessage()); + result.fail("getArrayStream()", + "Caught JsonException: " + ex.getLocalizedMessage()); + } + } + } + + /** + * Test {@code JsonParser getArrayStream()} method on non JSON array values. + */ + private void testGetNonArrayStream(final TestResult result) { + for (JsonValue value : NON_ARRAY_VALUES) { + final String data = jsonData(value); + System.out.println(" - getArrayStream() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + parser.getArrayStream(); + result.fail("getArrayStream()", + "Calling method on non array value shall throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println(" Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("getArrayStream()", + "Calling method on non array value shall throw IllegalStateException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonParser getValueStream()} method on simple JSON values in + * document root. + */ + private void testGetValueStream(final TestResult result) { + for (final JsonValue value : VALUES) { + final String data = jsonData(value); + System.out.println(" - getValueStream() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + final Stream<JsonValue> outStream = parser.getValueStream(); + int count = 0; + for (final Iterator<JsonValue> i = outStream.iterator(); i.hasNext();) { + final JsonValue out = i.next(); + if (operationFailed(value, out)) { + result.fail("getValueStream()", "Output Stream value " + + valueToString(out) + " shall be " + valueToString(value)); + } + count++; + } + if (count != 1) { + System.out.println(" Output Stream contains " + + Integer.toString(count) + " values, not 1"); + result.fail("getValueStream()", + "Output Stream does not contain exactly 1 JSON value"); + } + } + } + } + + /** + * Test {@code JsonParser getValueStream()} method inside compound JSON values + * in document root. + */ + private void testGetCompoundValueStream(final TestResult result) { + for (final JsonValue value : COMPOUND_VALUES) { + final String data = jsonData(value); + System.out.println(" - getValueStream() inside " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + parser.getValueStream(); + result.fail("getValueStream()", + "Calling method on non object value shall throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println(" Expected exception: " + e.getMessage()); + } catch (Throwable t) { + result.fail("getValueStream()", + "Calling method on non object value shall throw IllegalStateException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonParser skipArray()} method inside JSON array values. + * Expected result: Parser shall advance to the end of the stream after + * skipping an array which is the only value in the stream. + */ + private void testSkipArray(final TestResult result) { + for (final JsonArray value : ARRAY_VALUES) { + final String data = jsonData(value); + System.out.println(" - skipArray() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + parser.skipArray(); + if (parser.hasNext()) { + result.fail("skipArray()", + "Parser did not davance to the end of the array"); + } + } catch (Throwable t) { + System.out.println( + " " + t.getClass().getSimpleName() + ": " + t.getMessage()); + result.fail("skipArray()", + t.getClass().getSimpleName() + ": " + t.getMessage()); + } + } + } + + /** + * Test {@code JsonParser skipArray()} method outside JSON array values. + * Expected result: Parser shall not advance anywhere when called outside an + * array. Whole value shall match after {@code skipArray()} call because + * nothing shall happen in it. + */ + private void testSkipNonArray(final TestResult result) { + for (final JsonValue value : NON_ARRAY_VALUES) { + final String data = jsonData(value); + System.out.println(" - skipArray() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + parser.skipArray(); + final JsonValue out = parser.getValue(); + if (operationFailed(value, out)) { + result.fail("skipArray()", + "Output value " + valueToString(out) + " shall be " + + valueToString(value) + " even after skipArray()"); + } + } catch (Throwable t) { + System.out.println( + " " + t.getClass().getSimpleName() + ": " + t.getMessage()); + result.fail("skipArray()", + t.getClass().getSimpleName() + ": " + t.getMessage()); + } + } + } + + /** + * Test {@code JsonParser skipObject()} method inside JSON object values. + * Expected result: Parser shall advance to the end of the stream after + * skipping an object which is the only value in the stream. + */ + private void testSkipObject(final TestResult result) { + for (final JsonObject value : OBJ_VALUES) { + final String data = jsonData(value); + System.out.println(" - skipObject() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + parser.skipObject(); + if (parser.hasNext()) { + result.fail("skipObject()", + "Parser did not davance to the end of the object"); + } + } catch (Throwable t) { + System.out.println( + " " + t.getClass().getSimpleName() + ": " + t.getMessage()); + result.fail("skipObject()", + t.getClass().getSimpleName() + ": " + t.getMessage()); + } + } + } + + /** + * Test {@code JsonParser skipObject()} method outside JSON object values. + * Expected result: Parser shall not advance anywhere when called outside an + * object. Whole value shall match after {@code skipObject()} call because + * nothing shall happen in it. + */ + private void testSkipNonObject(final TestResult result) { + for (final JsonValue value : NON_OBJ_VALUES) { + final String data = jsonData(value); + System.out.println(" - skipObject() on " + data); + final StringReader strReader = new StringReader(data); + try (final JsonParser parser = Json.createParser(strReader)) { + parser.next(); + parser.skipObject(); + final JsonValue out = parser.getValue(); + if (operationFailed(value, out)) { + result.fail("skipObject()", + "Output value " + valueToString(out) + " shall be " + + valueToString(value) + " even after skipObject()"); + } + } catch (Throwable t) { + System.out.println( + " " + t.getClass().getSimpleName() + ": " + t.getMessage()); + result.fail("skipObject()", + t.getClass().getSimpleName() + ": " + t.getMessage()); + } + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + System.out.println(" Checking " + valueToString(out)); + return out == null || !assertEquals(check, out); + } + + /** + * Operation result check. + * + * @param check + * Expected Stream content. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonObject check, + final Stream<Map.Entry<String, JsonValue>> out) { + // Operation failed for null. + if (out == null) { + System.out.println(" Output is null"); + return true; + } + final Set<String> keys = new HashSet<>(check.size()); + // Clone key Set + for (final String key : check.keySet()) { + keys.add(key); + } + for (final Iterator<Map.Entry<String, JsonValue>> i = out.iterator(); i + .hasNext();) { + final Map.Entry<String, JsonValue> item = i.next(); + final JsonValue checkValue = check.get(item.getKey()); + System.out.println(" Checking " + valueToString(item.getValue())); + // Operation failed if values with the same key are not equal. + if (!item.getValue().equals(checkValue)) { + System.out.println(" check: " + valueToString(checkValue) + + " stream: " + valueToString(checkValue)); + return true; + } + keys.remove(item.getKey()); + } + // Operation failed if some unmatched keys remain in the set. + return !keys.isEmpty(); + } + + /** + * Operation result check. + * + * @param check + * Expected Stream content. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonArray check, + final Stream<JsonValue> out) { + // Operation failed for null. + if (out == null) { + System.out.println(" Output is null"); + return true; + } + final Iterator<JsonValue> ci = check.iterator(); + final Iterator<JsonValue> oi = out.iterator(); + // To exit cycle, at least one of iterators does not have next value. + while (ci.hasNext() && oi.hasNext()) { + final JsonValue checkValue = ci.next(); + final JsonValue outValue = oi.next(); + System.out.println(" Checking " + valueToString(outValue)); + if (!checkValue.equals(outValue)) { + System.out.println(" check: " + valueToString(checkValue) + + " stream: " + valueToString(checkValue)); + return true; + } + } + // Check still has values, something was missing in output. + if (ci.hasNext()) { + System.out.println(" Output contains less values than expected"); + return true; + } + // Output still has values, it contains more than expected. + if (oi.hasNext()) { + System.out.println(" Output contains more values than expected"); + return true; + } + return false; + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonreaderfactorytests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonreaderfactorytests/ClientTests.java new file mode 100644 index 0000000..ccb99bb --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonreaderfactorytests/ClientTests.java
@@ -0,0 +1,306 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonreaderfactorytests; + + +import jakarta.json.*; +import jakarta.json.stream.*; + +import java.io.*; +import java.nio.charset.Charset; + +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; +import java.util.Iterator; +import java.util.Map; +import java.util.ArrayList; + +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonReaderFactoryTest1 + * + * @assertion_ids: JSONP:JAVADOC:419; JSONP:JAVADOC:449; JSONP:JAVADOC:185; + * JSONP:JAVADOC:459; + * + * @test_Strategy: Tests the JsonReaderFactory API. + * + * JsonReaderFactory readerFactory = Json.createReaderFactory(Map<String, ?>); + * JsonReader reader1 = readerFactory.createReader(Reader) JsonReader reader2 + * = readerFactory.createReader(Reader) + */ + @Test + public void jsonReaderFactoryTest1() throws Fault { + boolean pass = true; + JsonReader reader1 = null; + JsonReader reader2 = null; + JsonObject jsonObject = null; + String jsonObjectText = "{\"foo\":\"bar\"}"; + try { + System.out.println("Create JsonReaderFactory with Map<String, ?> with EMPTY config"); + JsonReaderFactory readerFactory = Json + .createReaderFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = readerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + System.out.println("--------------------------------------------------"); + System.out.println("TEST CASE [JsonReaderFactory.createReader(Reader)]"); + System.out.println("--------------------------------------------------"); + System.out.println("Create 1st JsonReader using JsonReaderFactory"); + reader1 = readerFactory.createReader(new StringReader(jsonObjectText)); + if (reader1 == null) { + System.err.println("ReaderFactory failed to create reader1"); + pass = false; + } else { + jsonObject = reader1.readObject(); + reader1.close(); + + if (!JSONP_Util.assertEquals(jsonObject.size(), 1) + || !JSONP_Util.assertEquals(jsonObject.getString("foo"), "bar")) + pass = false; + } + + System.out.println("Create 2nd JsonReader using JsonReaderFactory"); + reader2 = readerFactory.createReader(new StringReader(jsonObjectText)); + if (reader2 == null) { + System.err.println("ReaderFactory failed to create reader2"); + pass = false; + } else { + jsonObject = reader2.readObject(); + reader2.close(); + + if (!JSONP_Util.assertEquals(jsonObject.size(), 1) + || !JSONP_Util.assertEquals(jsonObject.getString("foo"), "bar")) + pass = false; + } + + } catch (Exception e) { + throw new Fault("jsonReaderFactoryTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonReaderFactoryTest1 Failed"); + } + + /* + * @testName: jsonReaderFactoryTest2 + * + * @assertion_ids: JSONP:JAVADOC:420; JSONP:JAVADOC:449; JSONP:JAVADOC:185; + * JSONP:JAVADOC:459; + * + * @test_Strategy: Tests the JsonReaderFactory API. + * + * JsonReaderFactory readerFactory = Json.createReaderFactory(Map<String,?>); + * JsonReader reader1 = readerFactory.createReader(InputStream, Charset) + * JsonReader reader2 = readerFactory.createReader(InputStream, Charset) + * + * Create reader with both UTF-8 and UTF-16BE. + */ + @Test + public void jsonReaderFactoryTest2() throws Fault { + boolean pass = true; + JsonReader reader1 = null; + JsonReader reader2 = null; + JsonObject jsonObject = null; + String jsonObjectText = "{\"foo\":\"bar\"}"; + try { + System.out.println("Create JsonReaderFactory with Map<String, ?> with EMPTY config"); + JsonReaderFactory readerFactory = Json + .createReaderFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = readerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println( + "----------------------------------------------------------------"); + System.out.println( + "TEST CASE [JsonReaderFactory.createReader(InputStream, Charset)]"); + System.out.println( + "----------------------------------------------------------------"); + System.out.println( + "Create 1st JsonReader using JsonReaderFactory with UTF-8 encoding"); + InputStream is1 = JSONP_Util.getInputStreamFromString(jsonObjectText); + reader1 = readerFactory.createReader(is1, JSONP_Util.UTF_8); + if (reader1 == null) { + System.err.println("ReaderFactory failed to create reader1"); + pass = false; + } else { + jsonObject = reader1.readObject(); + reader1.close(); + + if (!JSONP_Util.assertEquals(jsonObject.size(), 1) + || !JSONP_Util.assertEquals(jsonObject.getString("foo"), "bar")) + pass = false; + } + + System.out.println( + "Create 2nd JsonReader using JsonReaderFactory with UTF-8 encoding"); + InputStream is2 = JSONP_Util.getInputStreamFromString(jsonObjectText); + reader2 = readerFactory.createReader(is2, JSONP_Util.UTF_8); + if (reader2 == null) { + System.err.println("ReaderFactory failed to create reader2"); + pass = false; + } else { + jsonObject = reader2.readObject(); + reader2.close(); + + if (!JSONP_Util.assertEquals(jsonObject.size(), 1) + || !JSONP_Util.assertEquals(jsonObject.getString("foo"), "bar")) + pass = false; + } + + } catch (Exception e) { + throw new Fault("jsonReaderFactoryTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonReaderFactoryTest2 Failed"); + } + + /* + * @testName: jsonReaderFactoryTest3 + * + * @assertion_ids: JSONP:JAVADOC:429; JSONP:JAVADOC:449; JSONP:JAVADOC:185; + * JSONP:JAVADOC:459; + * + * @test_Strategy: Tests the JsonReaderFactory API. + * + * JsonReaderFactory readerFactory = Json.createReaderFactory(Map<String, ?>); + * JsonReader reader1 = readerFactory.createReader(InputStream) JsonReader + * reader2 = readerFactory.createReader(InputStream) + */ + @Test + public void jsonReaderFactoryTest3() throws Fault { + boolean pass = true; + JsonReader reader1 = null; + JsonReader reader2 = null; + JsonObject jsonObject = null; + String jsonObjectText = "{\"foo\":\"bar\"}"; + try { + System.out.println("Create JsonReaderFactory with Map<String, ?> with EMPTY config"); + JsonReaderFactory readerFactory = Json + .createReaderFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = readerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("-------------------------------------------------------"); + System.out.println("TEST CASE [JsonReaderFactory.createReader(InputStream)]"); + System.out.println("-------------------------------------------------------"); + System.out.println("Create 1st JsonReader using JsonReaderFactory"); + InputStream is1 = JSONP_Util.getInputStreamFromString(jsonObjectText); + reader1 = readerFactory.createReader(is1); + if (reader1 == null) { + System.err.println("ReaderFactory failed to create reader1"); + pass = false; + } else { + jsonObject = reader1.readObject(); + reader1.close(); + + if (!JSONP_Util.assertEquals(jsonObject.size(), 1) + || !JSONP_Util.assertEquals(jsonObject.getString("foo"), "bar")) + pass = false; + } + + System.out.println("Create 2nd JsonReader using JsonReaderFactory"); + InputStream is2 = JSONP_Util.getInputStreamFromString(jsonObjectText); + reader2 = readerFactory.createReader(is2); + if (reader2 == null) { + System.err.println("ReaderFactory failed to create reader2"); + pass = false; + } else { + jsonObject = reader2.readObject(); + reader2.close(); + + if (!JSONP_Util.assertEquals(jsonObject.size(), 1) + || !JSONP_Util.assertEquals(jsonObject.getString("foo"), "bar")) + pass = false; + } + + } catch (Exception e) { + throw new Fault("jsonReaderFactoryTest3 Failed: ", e); + } + if (!pass) + throw new Fault("jsonReaderFactoryTest3 Failed"); + } + + /* + * @testName: jsonReaderFactoryTest4 + * + * @assertion_ids: JSONP:JAVADOC:449; JSONP:JAVADOC:459; + * + * @test_Strategy: Tests the JsonReaderFactory API. + * + * JsonReaderFactory readerFactory = Json.createReaderFactory(Map<String, ?>); + * Map<String, ?> config = JsonReaderFactory.getConfigInUse(); + * + * Test for the following 3 scenarios: 1) no supported provider property + * (empty config) 2) non supported provider property + */ + @Test + public void jsonReaderFactoryTest4() throws Fault { + boolean pass = true; + JsonReaderFactory readerFactory; + Map<String, ?> config; + try { + System.out.println("----------------------------------------------"); + System.out.println("Test scenario1: no supported provider property"); + System.out.println("----------------------------------------------"); + System.out.println("Create JsonReaderFactory with Map<String, ?> with EMPTY config"); + readerFactory = Json.createReaderFactory(JSONP_Util.getEmptyConfig()); + config = readerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("-----------------------------------------------"); + System.out.println("Test scenario2: non supported provider property"); + System.out.println("-----------------------------------------------"); + System.out.println("Create JsonReaderFactory with Map<String, ?> with FOO config"); + readerFactory = Json.createReaderFactory(JSONP_Util.getFooConfig()); + config = readerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonReaderFactoryTest4 Failed: ", e); + } + if (!pass) + throw new Fault("jsonReaderFactoryTest4 Failed"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonreadertests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonreadertests/ClientTests.java new file mode 100644 index 0000000..8a1b988 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonreadertests/ClientTests.java
@@ -0,0 +1,3232 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonreadertests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +import java.io.*; +import java.util.*; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.json.*; +import jakarta.json.stream.*; + +// $Id$ +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Utility Methods */ + + /* + * compareJsonObjectForUTFEncodedTests + */ + private boolean compareJsonObjectForUTFEncodedTests(JsonObject jsonObject) { + boolean pass = true; + System.out.println("Comparing JsonObject values to expected results."); + String expString = "stringValue"; + String actString = jsonObject.getJsonString("stringName").getString(); + if (!JSONP_Util.assertEquals(expString, actString)) + pass = false; + JsonObject actObject = jsonObject.getJsonObject("objectName"); + expString = "bar"; + actString = actObject.getJsonString("foo").getString(); + if (!JSONP_Util.assertEquals(expString, actString)) + pass = false; + JsonArray actArray = jsonObject.getJsonArray("arrayName"); + if (!JSONP_Util.assertEquals(1, actArray.getJsonNumber(0).intValue()) + || !JSONP_Util.assertEquals(2, actArray.getJsonNumber(1).intValue()) + || !JSONP_Util.assertEquals(3, actArray.getJsonNumber(2).intValue())) + pass = false; + return pass; + } + + /* Tests */ + + /* + * @testName: readEmptyArrayTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:184; + * + * @test_Strategy: Test read of an empty array "[]" from stream. Use + * JsonReader.readArray() API call. + * + */ + @Test + public void readEmptyArrayTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + String expJsonText = "[]"; + System.out.println("Testing read of " + expJsonText); + reader = Json.createReader(new StringReader(expJsonText)); + JsonArray array = reader.readArray(); + pass = JSONP_Util.assertEqualsEmptyArrayList(array); + } catch (Exception e) { + throw new Fault("readEmptyArrayTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readEmptyArrayTest Failed"); + } + + /* + * @testName: readEscapeCharsInArrayTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:184; + * + * @test_Strategy: Test read of an array from a resource file with special + * chars in data. Use JsonReader.readArray() API call. Test scenario: Read + * string of JSON text containing a JSON array from resource file with + * following data: [ "popeye\"\\\/\b\f\n\r\tolive" ] + * + * These characters are backslash escape'd as follows: \" \\ \/ \b \f \n \r \t + * + * Create a JsonWriter to write above JsonArray to a string of JSON text. + * Re-read JsonWriter text back into a JsonArray Compare expected JSON array + * with actual JSON array for equality. + * + */ + @Test + public void readEscapeCharsInArrayTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + String resourceFile = "jsonArrayWithEscapeCharsData.json"; + String expString = "popeye" + JSONP_Data.escapeCharsAsString + "olive"; + try { + + System.out.println("Reading contents of resource file " + resourceFile); + String readerContents = JSONP_Util + .getContentsOfResourceAsString(resourceFile); + System.out.println("readerContents=" + readerContents); + + System.out.println("Testing read of resource contents: " + readerContents); + reader = Json.createReader(new StringReader(readerContents)); + JsonArray expJsonArray = reader.readArray(); + + System.out.println("Dump of expJsonArray"); + JSONP_Util.dumpJsonArray(expJsonArray); + + System.out.println("Comparing JsonArray values with expected results."); + String actString = expJsonArray.getJsonString(0).getString(); + if (!JSONP_Util.assertEquals(expString, actString)) + pass = false; + + System.out.println("Write the JsonArray 'expJsonArray' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeArray(expJsonArray); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String writerContents = sWriter.toString(); + + System.out.println("Create actJsonArray from read of writer contents: " + + writerContents); + reader = Json.createReader(new StringReader(writerContents)); + JsonArray actJsonArray = reader.readArray(); + + System.out.println("Dump of actJsonArray"); + JSONP_Util.dumpJsonArray(actJsonArray); + + System.out.println("Compare expJsonArray and actJsonArray for equality"); + if (!JSONP_Util.assertEqualsJsonArrays(expJsonArray, actJsonArray)) + pass = false; + } catch (Exception e) { + throw new Fault("readEscapeCharsInArrayTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readEscapeCharsInArrayTest Failed"); + } + + /* + * @testName: readEscapeUnicodeCharsInArrayTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:184; + * + * @test_Strategy: Test read of an array with unicode chars escaped and not + * escaped. Use JsonReader.readArray() API call. Test scenario: Read string of + * JSON text containing a JSON array with the following data: [ + * "\\u0000\u00ff\\uff00\uffff" ] + * + * Notice unicode \u0000 and \uff00 is escaped but \u00ff and \uffff is not. + * + * Compare expected JSON String with actual JSON String for equality. + * + */ + @Test + public void readEscapeUnicodeCharsInArrayTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + String unicodeTextString = "[\"\\u0000\u00ff\\uff00\uffff\"]"; + String expResult = "\u0000\u00ff\uff00\uffff"; + try { + System.out.println("Reading array of escaped and non escaped unicode chars."); + reader = Json.createReader(new StringReader(unicodeTextString)); + JsonArray array = reader.readArray(); + String actResult = array.getJsonString(0).getString(); + pass = JSONP_Util.assertEquals(expResult, actResult); + } catch (Exception e) { + throw new Fault("readEscapeUnicodeCharsInArrayTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readEscapeUnicodeCharsInArrayTest Failed"); + } + + /* + * @testName: readEscapeUnicodeControlCharsInArrayTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:184; + * + * @test_Strategy: Test read of an array with unicode control chars escaped. + * Use JsonReader.readArray() API call. Test scenario: Read string of JSON + * text containing unicode control chars escaped as a Json Array. + * + * Compare expected JSON String with actual JSON String for equality. + * + */ + @Test + public void readEscapeUnicodeControlCharsInArrayTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + String unicodeTextString = "[\"" + JSONP_Data.unicodeControlCharsEscaped + + "\"]"; + String expResult = JSONP_Data.unicodeControlCharsNonEscaped; + try { + System.out.println("Reading array of escaped and non escaped unicode chars."); + reader = Json.createReader(new StringReader(unicodeTextString)); + JsonArray array = reader.readArray(); + String actResult = array.getJsonString(0).getString(); + pass = JSONP_Util.assertEquals(expResult, actResult); + } catch (Exception e) { + throw new Fault("readEscapeUnicodeControlCharsInArrayTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readEscapeUnicodeControlCharsInArrayTest Failed"); + } + + /* + * @testName: readEmptyObjectTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:185; + * + * @test_Strategy: Test read of an empty object "{}" from stream. Use + * JsonReader.readObject() API call. + * + */ + @Test + public void readEmptyObjectTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + String expJsonText = "{}"; + System.out.println("Testing read of " + expJsonText); + reader = Json.createReader(new StringReader(expJsonText)); + JsonObject object = reader.readObject(); + pass = JSONP_Util.assertEqualsEmptyObjectMap(object); + } catch (Exception e) { + throw new Fault("readEmptyObjectTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readEmptyObjectTest Failed"); + } + + /* + * @testName: readEscapeCharsInObjectTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:185; + * + * @test_Strategy: Test read of an object from a resource file with special + * chars in data. Use JsonReader.readObject() API call. Test scenario: Read + * string of JSON text containing a JSON object from resource file with + * following data: { "specialChars" : "popeye\"\\\/\b\f\n\r\tolive" } + * + * These characters are backslash escape'd as follows: \" \\ \/ \b \f \n \r \t + * + * Create a JsonWriter to write above JsonObject to a string of JSON text. + * Re-read JsonWriter text back into a JsonObject Compare expected JSON object + * with actual JSON object for equality. + * + */ + @Test + public void readEscapeCharsInObjectTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + String resourceFile = "jsonObjectWithEscapeCharsData.json"; + String expString = "popeye" + JSONP_Data.escapeCharsAsString + "olive"; + try { + + System.out.println("Reading contents of resource file " + resourceFile); + String readerContents = JSONP_Util + .getContentsOfResourceAsString(resourceFile); + System.out.println("readerContents=" + readerContents); + + System.out.println("Testing read of resource contents: " + readerContents); + reader = Json.createReader(new StringReader(readerContents)); + JsonObject expJsonObject = reader.readObject(); + + System.out.println("Dump of expJsonObject"); + JSONP_Util.dumpJsonObject(expJsonObject); + + System.out.println("Comparing JsonArray values with expected results."); + String actString = expJsonObject.getJsonString("escapeChars").getString(); + if (!JSONP_Util.assertEquals(expString, actString)) + pass = false; + + System.out.println("Write the JsonObject 'expJsonObject' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeObject(expJsonObject); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String writerContents = sWriter.toString(); + + System.out.println("Create actJsonObject from read of writer contents: " + + writerContents); + reader = Json.createReader(new StringReader(writerContents)); + JsonObject actJsonObject = reader.readObject(); + + System.out.println("Dump of actJsonObject"); + JSONP_Util.dumpJsonObject(actJsonObject); + + System.out.println("Compare expJsonObject and actJsonObject for equality"); + if (!JSONP_Util.assertEqualsJsonObjects(expJsonObject, actJsonObject)) + pass = false; + } catch (Exception e) { + throw new Fault("readEscapeCharsInObjectTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readEscapeCharsInObjectTest Failed"); + } + + /* + * @testName: readEscapeUnicodeCharsInObjectTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:185; + * + * @test_Strategy: Test read of an object with unicode chars escaped and not + * escaped. Use JsonReader.readObject() API call. Test scenario: Read string + * of JSON text containing a JSON object with the following data: { + * "unicodechars":"\\u0000\u00ff\\uff00\uffff" ] + * + * Notice unicode \u0000 and \uff00 is escaped but \u00ff and \uffff is not. + * + * Compare expected JSON String with actual JSON String for equality. + * + */ + @Test + public void readEscapeUnicodeCharsInObjectTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + String unicodeTextString = "{\"unicodechars\":\"\\u0000\u00ff\\uff00\uffff\"}"; + String expResult = "\u0000\u00ff\uff00\uffff"; + try { + System.out.println("Reading object of escaped and non escaped unicode chars."); + reader = Json.createReader(new StringReader(unicodeTextString)); + JsonObject object = reader.readObject(); + String actResult = object.getJsonString("unicodechars").getString(); + pass = JSONP_Util.assertEquals(expResult, actResult); + } catch (Exception e) { + throw new Fault("readEscapeUnicodeCharsInObjectTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readEscapeUnicodeCharsInObjectTest Failed"); + } + + /* + * @testName: readEscapeUnicodeControlCharsInObjectTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:185; + * + * @test_Strategy: Test read of an array with unicode control chars escaped. + * Use JsonReader.readObject() API call. Test scenario: Read string of JSON + * text containing unicode control chars escaped as a Json Object. + * + * Compare expected JSON String with actual JSON String for equality. + * + */ + @Test + public void readEscapeUnicodeControlCharsInObjectTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + String unicodeTextString = "{\"unicodechars\":\"" + + JSONP_Data.unicodeControlCharsEscaped + "\"}"; + String expResult = JSONP_Data.unicodeControlCharsNonEscaped; + try { + System.out.println("Reading array of escaped and non escaped unicode chars."); + reader = Json.createReader(new StringReader(unicodeTextString)); + JsonObject object = reader.readObject(); + String actResult = object.getJsonString("unicodechars").getString(); + pass = JSONP_Util.assertEquals(expResult, actResult); + } catch (Exception e) { + throw new Fault("readEscapeUnicodeControlCharsInObjectTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readEscapeUnicodeControlCharsInObjectTest Failed"); + } + + /* + * @testName: readArrayTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:184; + * + * @test_Strategy: Test read of an array containing various types from stream. + * Use JsonReader.readArray() API call. [true, false, null, "booyah", + * 2147483647, 9223372036854775807, 1.7976931348623157E308, + * [true,false,null,"bingo",-2147483648,-9223372036854775808,4.9E-324], + * {"true":true,"false":false,"null":null,"bonga":"boo","int":1,"double":10.4} + * ] Test scenario: Read string of JSON text above consisting of a JSON array + * into a JsonArray object. Create an expected List of JsonArray values for + * use in test comparison. Compare expected list of JsonArray values with + * actual list for equality. + * + */ + @Test + public void readArrayTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + String jsonText = "[true,false,null,\"booyah\",2147483647,9223372036854775807,1.7976931348623157E308," + + "[true,false,null,\"bingo\",-2147483648,-9223372036854775808,4.9E-324]," + + "{\"true\":true,\"false\":false,\"null\":null,\"bonga\":\"boo\",\"int\":1," + + "\"double\":10.4}]"; + + System.out.println("Create the expected list of JsonArray values"); + List<JsonValue> expList = new ArrayList<>(); + expList.add(JsonValue.TRUE); + expList.add(JsonValue.FALSE); + expList.add(JsonValue.NULL); + expList.add(JSONP_Util.createJsonString("booyah")); + expList.add(JSONP_Util.createJsonNumber(Integer.MAX_VALUE)); + expList.add(JSONP_Util.createJsonNumber(Long.MAX_VALUE)); + expList.add(JSONP_Util.createJsonNumber(Double.MAX_VALUE)); + JsonArray array = Json.createArrayBuilder().add(JsonValue.TRUE) + .add(JsonValue.FALSE).add(JsonValue.NULL).add("bingo") + .add(Integer.MIN_VALUE).add(Long.MIN_VALUE).add(Double.MIN_VALUE) + .build(); + JsonObject object = Json.createObjectBuilder().add("true", JsonValue.TRUE) + .add("false", JsonValue.FALSE).add("null", JsonValue.NULL) + .add("bonga", "boo").add("int", 1).add("double", 10.4).build(); + expList.add(array); + expList.add(object); + + System.out.println("Testing read of " + jsonText); + reader = Json.createReader(new StringReader(jsonText)); + JsonArray myJsonArray = reader.readArray(); + + List<JsonValue> actList = myJsonArray; + System.out.println( + "Compare actual list of JsonArray values with expected list of JsonArray values"); + pass = JSONP_Util.assertEqualsList(expList, actList); + } catch (Exception e) { + throw new Fault("readArrayTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readArrayTest Failed"); + } + + /* + * @testName: readArrayTest2 + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:184; + * JSONP:JAVADOC:178; + * + * @test_Strategy: Test read of an array containing various types from stream. + * Use JsonReader.readArray() API call. [true, false, null, "booyah", + * 2147483647, 9223372036854775807, 1.7976931348623157E308, + * [true,false,null,"bingo",-2147483648,-9223372036854775808,4.9E-324], + * {"true":true,"false":false,"null":null,"bonga":"boo","int":1,"double":10.4} + * ] Test Scenario: Create an expected JsonArray of the above JSON array for + * use in test comparison. Create a JsonWriter to write the above JsonArray to + * a string of JSON text. Next call JsonReader to read the JSON text from the + * JsonWriter to a JsonArray object. Compare expected JsonArray object with + * actual JsonArray object for equality. + * + */ + @Test + public void readArrayTest2() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + System.out.println("Create the expected list of JsonArray values"); + JsonArray expJsonArray = Json.createArrayBuilder().add(JsonValue.TRUE) + .add(JsonValue.FALSE).add(JsonValue.NULL).add("booyah") + .add(Integer.MAX_VALUE).add(Long.MAX_VALUE).add(Double.MAX_VALUE) + .add(Json.createArrayBuilder().add(JsonValue.TRUE) + .add(JsonValue.FALSE).add(JsonValue.NULL).add("bingo") + .add(Integer.MIN_VALUE).add(Long.MIN_VALUE).add(Double.MIN_VALUE)) + .add(Json.createObjectBuilder().add("true", JsonValue.TRUE) + .add("false", JsonValue.FALSE).add("null", JsonValue.NULL) + .add("bonga", "boo").add("int", 1).add("double", 10.4)) + .build(); + + System.out.println("Write the JsonArray 'expJsonArray' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeArray(expJsonArray); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String jsonText = sWriter.toString(); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + jsonText); + + System.out.println("Testing read of " + jsonText); + reader = Json.createReader(JSONP_Util.getInputStreamFromString(jsonText)); + JsonArray actJsonArray = reader.readArray(); + + System.out.println("Compare expJsonArray and actJsonArray for equality"); + pass = JSONP_Util.assertEqualsJsonArrays(expJsonArray, actJsonArray); + } catch (Exception e) { + throw new Fault("readArrayTest2 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readArrayTest2 Failed"); + } + + /* + * @testName: readArrayTest3 + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:449; JSONP:JAVADOC:184; + * JSONP:JAVADOC:419; + * + * @test_Strategy: Test read of an array containing various types from stream. + * Use JsonReader.readArray() API call. [true, false, null, "booyah", + * 2147483647, 9223372036854775807, + * [true,false,null,"bingo",-2147483648,-9223372036854775808], + * {"true":true,"false":false,"null":null,"bonga":"boo","int":1} ] Test + * scenario: Read string of JSON text above consisting of a JSON array into a + * JsonArray object with an empty configuration. Create a JsonWriter to write + * the above JsonArray to a string of JSON text. Compare expected JSON text + * with actual JSON text for equality. + * + * Tests the following API's: JsonReader = + * Json.createReaderFactory(Map<String,?>).createReader(Reader) JsonArray + * array = JsonReader.readArray() + * + */ + @Test + public void readArrayTest3() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + String expJsonText = "[true,false,null,\"booyah\",2147483647,9223372036854775807," + + "[true,false,null,\"bingo\",-2147483648,-9223372036854775808]," + + "{\"true\":true,\"false\":false,\"null\":null,\"bonga\":\"boo\",\"int\":1}]"; + + System.out.println("Testing read of " + expJsonText); + reader = Json.createReaderFactory(JSONP_Util.getEmptyConfig()) + .createReader(new StringReader(expJsonText)); + JsonArray myJsonArray = reader.readArray(); + + System.out.println("Write the JsonArray 'myJsonArray' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeArray(myJsonArray); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String actJsonText = sWriter.toString(); + + System.out.println("Compare actual JSON text with expected JSON text"); + pass = JSONP_Util.assertEqualsJsonText(expJsonText, actJsonText); + } catch (Exception e) { + throw new Fault("readArrayTest3 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readArrayTest3 Failed"); + } + + /* + * @testName: readArrayTest4 + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:420; JSONP:JAVADOC:184; + * JSONP:JAVADOC:449; + * + * @test_Strategy: Test read of an array from a resource file with various + * amounts of data. Use JsonReader.readArray() API call. Test scenario: Read + * InputStream of JSON text containing a JSON array from resource file with + * various amounts of data use UTF-8 encoding. Create a JsonWriter to write + * above JsonArray to a string of JSON text. Re-read JsonWriter text back into + * a JsonArray Compare expected JSON array with actual JSON array for + * equality. + * + */ + @Test + public void readArrayTest4() throws Fault { + boolean pass = true; + JsonReader reader = null; + String resourceFile = "jsonArrayWithAllTypesOfData.json"; + try { + System.out.println( + "Read contents of InputStream from resource file: " + resourceFile); + Map<String, ?> config = JSONP_Util.getEmptyConfig(); + reader = Json.createReaderFactory(config).createReader( + JSONP_Util.getInputStreamFromResource(resourceFile), + JSONP_Util.UTF_8); + JsonArray expJsonArray = reader.readArray(); + + System.out.println("Dump of expJsonArray"); + JSONP_Util.dumpJsonArray(expJsonArray); + + System.out.println("Write the JsonArray 'expJsonArray' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeArray(expJsonArray); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String writerContents = sWriter.toString(); + + System.out.println("Create actJsonArray from read of writer contents: " + + writerContents); + reader = Json.createReader(new StringReader(writerContents)); + JsonArray actJsonArray = reader.readArray(); + + System.out.println("Dump of actJsonArray"); + JSONP_Util.dumpJsonArray(actJsonArray); + + System.out.println("Compare expJsonArray and actJsonArray for equality"); + pass = JSONP_Util.assertEqualsJsonArrays(expJsonArray, actJsonArray); + } catch (Exception e) { + throw new Fault("readArrayTest4 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readArrayTest4 Failed"); + } + + /* + * @testName: readArrayTest5 + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:181; + * JSONP:JAVADOC:420; JSONP:JAVADOC:449; + * + * @test_Strategy: Test read of an array from a resource file with lots of + * nesting. Use JsonReader.read() API call. Test scenario: Read InputStream of + * JSON text containing a JSON array from resource file with lots of nesting + * use UTF-8 encoding with empty configuration. Create a JsonWriter to write + * above JsonArray to a string of JSON text. Compare expected JSON text with + * actual JSON text for equality. Filter all text output to remove whitespace + * before comparison. + * + * Tests the following API's: JsonReader = + * Json.createReaderFactory(Map<String,?>).createReader(InputStream, Charset) + * JsonArray array = (JsonArray)JsonReader.read() + * + * + */ + @Test + public void readArrayTest5() throws Fault { + boolean pass = true; + JsonReader reader = null; + String resourceFile = "jsonArrayWithLotsOfNestedObjectsData.json"; + try { + System.out.println("Reading contents of resource file " + resourceFile); + String readerContents = JSONP_Util + .getContentsOfResourceAsString(resourceFile); + System.out.println("readerContents=" + readerContents); + + // Create expected JSON text from resource contents filtered of whitespace + // for comparison + System.out.println("Filter readerContents of whitespace for comparison"); + String expJsonText = JSONP_Util.removeWhitespace(readerContents); + + System.out.println( + "Read contents of InputStream from resource file: " + resourceFile); + reader = Json.createReaderFactory(JSONP_Util.getEmptyConfig()) + .createReader(JSONP_Util.getInputStreamFromResource(resourceFile), + JSONP_Util.UTF_8); + JsonArray myJsonArray = (JsonArray) reader.read(); + + System.out.println("Write the JsonArray 'myJsonArray' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeArray(myJsonArray); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String writerContents = sWriter.toString(); + + System.out.println("Dump contents of the JsonWriter as a String"); + System.out.println("writerContents=" + writerContents); + + System.out.println("Filter writerContents of whitespace for comparison"); + String actJsonText = JSONP_Util.removeWhitespace(writerContents); + + System.out.println("Compare actual JSON text with expected JSON text"); + pass = JSONP_Util.assertEqualsJsonText(expJsonText, actJsonText); + } catch (Exception e) { + throw new Fault("readArrayTest5 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readArrayTest5 Failed"); + } + + /* + * @testName: readArrayEncodingTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:420; JSONP:JAVADOC:449; + * JSONP:JAVADOC:184; + * + * @test_Strategy: Test read of a JsonArray from a resource file using both + * encodings of UTF-8 and UTF-16BE. + * + * Test scenario: For each encoding read the appropriate resource file + * containing a string value. Call JsonArray.getJsonString() to get the value + * of the JsonString. Compare expected string with actual string for equality. + */ + @Test + public void readArrayEncodingTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + String expString = "a\u65e8\u452c\u8b9e\u6589\u5c57\u5217z"; + String resourceFileUTF8 = "jsonArrayUTF8.json"; + String resourceFileUTF16BE = "jsonArrayUTF16BE.json"; + Map<String, ?> config = JSONP_Util.getEmptyConfig(); + try { + System.out.println("Reading contents of resource file using UTF-8 encoding " + + resourceFileUTF8); + InputStream is = JSONP_Util.getInputStreamFromResource(resourceFileUTF8); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_8); + JsonArray jsonArray = reader.readArray(); + System.out.println("Comparing JsonArray values with expected results."); + String actString = jsonArray.getJsonString(0).getString(); + if (!JSONP_Util.assertEquals(expString, actString)) + pass = false; + } catch (Exception e) { + throw new Fault("readArrayEncodingTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + try { + System.out.println("Reading contents of resource file using UTF-16BE encoding " + + resourceFileUTF16BE); + InputStream is = JSONP_Util + .getInputStreamFromResource(resourceFileUTF16BE); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_16BE); + JsonArray jsonArray = reader.readArray(); + System.out.println("Comparing JsonArray values with expected results."); + String actString = jsonArray.getJsonString(0).getString(); + if (!JSONP_Util.assertEquals(expString, actString)) + pass = false; + } catch (Exception e) { + throw new Fault("readArrayEncodingTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readArrayEncodingTest Failed"); + } + + /* + * @testName: readObjectTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:185; + * + * @test_Strategy: Test read of an object containing various types from + * stream. Use JsonReader.readObject() API call. {"true":true, "false":false, + * "null":null, "booyah":"booyah", "int":2147483647, + * "long":9223372036854775807, "double":1.7976931348623157E308, + * "array":[true,false,null,"bingo",-2147483648,-9223372036854775808,4.9E-324] + * , "object":{"true":true,"false":false,"null":null,"bonga":"boo","int":1, + * "double":10.4} } Test scenario: Read string of JSON text above consisting + * of a JSON object into a JsonObject object. Create an expected map of + * JsonObject values for use in test comparison. Compare expected map of + * JsonObject values with actual map for equality. + * + */ + @Test + public void readObjectTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + String expJsonText = "{\"true\":true,\"false\":false,\"null\":null,\"booyah\":\"booyah\",\"int\":2147483647," + + "\"long\":9223372036854775807,\"double\":1.7976931348623157E308," + + "\"array\":[true,false,null,\"bingo\",-2147483648,-9223372036854775808,4.9E-324]," + + "\"object\":{\"true\":true,\"false\":false,\"null\":null,\"bonga\":\"boo\",\"int\":1," + + "\"double\":10.4}}"; + + System.out.println("Create the expected map of JsonObject values"); + Map<String, JsonValue> expMap = new HashMap<>(); + expMap.put("true", JsonValue.TRUE); + expMap.put("false", JsonValue.FALSE); + expMap.put("null", JsonValue.NULL); + expMap.put("booyah", JSONP_Util.createJsonString("booyah")); + expMap.put("int", JSONP_Util.createJsonNumber(Integer.MAX_VALUE)); + expMap.put("long", JSONP_Util.createJsonNumber(Long.MAX_VALUE)); + expMap.put("double", JSONP_Util.createJsonNumber(Double.MAX_VALUE)); + JsonArray array = Json.createArrayBuilder().add(JsonValue.TRUE) + .add(JsonValue.FALSE).add(JsonValue.NULL).add("bingo") + .add(Integer.MIN_VALUE).add(Long.MIN_VALUE).add(Double.MIN_VALUE) + .build(); + JsonObject object = Json.createObjectBuilder().add("true", JsonValue.TRUE) + .add("false", JsonValue.FALSE).add("null", JsonValue.NULL) + .add("bonga", "boo").add("int", 1).add("double", 10.4).build(); + expMap.put("array", array); + expMap.put("object", object); + + System.out.println("Testing read of " + expJsonText); + reader = Json.createReader(new StringReader(expJsonText)); + JsonObject myJsonObject = reader.readObject(); + + Map<String, JsonValue> actMap = myJsonObject; + System.out.println( + "Compare actual map of JsonObject values with expected map of JsonObject values"); + pass = JSONP_Util.assertEqualsMap(expMap, actMap); + } catch (Exception e) { + throw new Fault("readObjectTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readObjectTest Failed"); + } + + /* + * @testName: readObjectTest2 + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:178; JSONP:JAVADOC:185; + * + * @test_Strategy: Test read of an object containing various types from + * stream. Use JsonReader.readObject() API call. {"true":true, "false":false, + * "null":null, "booyah":"booyah", "int":2147483647, + * "long":9223372036854775807, "double":1.7976931348623157E308, + * "array":[true,false,null,"bingo",-2147483648,-9223372036854775808,4.9E-324] + * , "object":{"true":true,"false":false,"null":null,"bonga":"boo","int":1, + * "double":10.4} } Test Scenario: Create an expected JsonObject of the above + * JSON object for use in test comparison. Create a JsonWriter to write the + * above JsonObject to a string of JSON text. Next call JsonReader to read the + * JSON text from the JsonWriter to a JsonObject object. Compare expected + * JsonObject object with actual JsonObject object for equality. + * + */ + @Test + public void readObjectTest2() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + System.out.println("Create the expected list of JsonObject values"); + JsonObject expJsonObject = Json.createObjectBuilder() + .add("true", JsonValue.TRUE).add("false", JsonValue.FALSE) + .add("null", JsonValue.NULL).add("booyah", "booyah") + .add("int", Integer.MAX_VALUE).add("long", Long.MAX_VALUE) + .add("double", Double.MAX_VALUE) + .add("array", + Json.createArrayBuilder().add(JsonValue.TRUE).add(JsonValue.FALSE) + .add(JsonValue.NULL).add("bingo").add(Integer.MIN_VALUE) + .add(Long.MIN_VALUE).add(Double.MIN_VALUE)) + .add("object", + Json.createObjectBuilder().add("true", JsonValue.TRUE) + .add("false", JsonValue.FALSE).add("null", JsonValue.NULL) + .add("bonga", "boo").add("int", 1).add("double", 10.4)) + .build(); + + System.out.println("Write the JsonObject 'expJsonObject' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeObject(expJsonObject); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String jsonText = sWriter.toString(); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + jsonText); + + System.out.println("Testing read of " + jsonText); + reader = Json.createReader(JSONP_Util.getInputStreamFromString(jsonText)); + JsonObject actJsonObject = reader.readObject(); + + System.out.println("Compare expJsonObject and actJsonObject for equality"); + pass = JSONP_Util.assertEqualsJsonObjects(expJsonObject, actJsonObject); + } catch (Exception e) { + throw new Fault("readObjectTest2 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readObjectTest2 Failed"); + } + + /* + * @testName: readObjectTest3 + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:185; JSONP:JAVADOC:419; + * JSONP:JAVADOC:449; + * + * @test_Strategy: Test read of an object containing various types from + * stream. Use JsonReader.readObject() API call. {"true":true, "false":false, + * "null":null, "booyah":"booyah", "int":2147483647, + * "long":9223372036854775807, + * "array":[true,false,null,"bingo",-2147483648,-9223372036854775808], + * "object":{"true":true,"false":false,"null":null,"bonga":"boo","int":1} } + * Test scenario: Read string of JSON text above consisting of a JSON object + * into a JsonObject object with an empty configuration. Create a JsonWriter + * to write the above JsonObject to a string of JSON text. Compare expected + * JSON text with actual JSON text for equality. + * + * Tests the following API's: JsonReader = + * Json.createReaderFactory(Map<String,?>).createReader(Reader) JsonObject + * object = JsonReader.readObject() + * + * + */ + @Test + public void readObjectTest3() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + String expJsonText = "{\"true\":true,\"false\":false,\"null\":null,\"booyah\":\"booyah\",\"int\":2147483647,\"long\":9223372036854775807," + + "\"array\":[true,false,null,\"bingo\",-2147483648,-9223372036854775808]," + + "\"object\":{\"true\":true,\"false\":false,\"null\":null,\"bonga\":\"boo\",\"int\":1}}"; + + System.out.println("Testing read of " + expJsonText); + reader = Json.createReaderFactory(JSONP_Util.getEmptyConfig()) + .createReader(new StringReader(expJsonText)); + JsonObject myJsonObject = reader.readObject(); + + System.out.println("Write the JsonObject 'myJsonObject' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeObject(myJsonObject); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String actJsonText = sWriter.toString(); + + System.out.println("Compare actual JSON text with expected JSON text"); + pass = JSONP_Util.assertEqualsJsonText(expJsonText, actJsonText); + } catch (Exception e) { + throw new Fault("readObjectTest3 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readObjectTest3 Failed"); + } + + /* + * @testName: readObjectTest4 + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:420; + * JSONP:JAVADOC:449; + * + * @test_Strategy: Test read of an object from a resource file with various + * amounts of data. Use JsonReader.readObject() API call. Test scenario: Read + * InputStream of JSON text containing a JSON object from resource file with + * various amounts of data use UTF-8 encoding. Create a JsonWriter to write + * above JsonObject to a string of JSON text. Re-read JsonWriter text back + * into a JsonObject Compare expected JSON object with actual JSON object for + * equality. + * + */ + @Test + public void readObjectTest4() throws Fault { + boolean pass = true; + JsonReader reader = null; + String resourceFile = "jsonObjectWithAllTypesOfData.json"; + try { + System.out.println( + "Read contents of InputStream from resource file: " + resourceFile); + Map<String, ?> config = JSONP_Util.getEmptyConfig(); + reader = Json.createReaderFactory(config).createReader( + JSONP_Util.getInputStreamFromResource(resourceFile), + JSONP_Util.UTF_8); + JsonObject expJsonObject = reader.readObject(); + + System.out.println("Dump of expJsonObject"); + JSONP_Util.dumpJsonObject(expJsonObject); + + System.out.println("Write the JsonObject 'expJsonObject' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeObject(expJsonObject); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String writerContents = sWriter.toString(); + + System.out.println("Create actJsonObject from read of writer contents: " + + writerContents); + reader = Json.createReader(new StringReader(writerContents)); + JsonObject actJsonObject = reader.readObject(); + + System.out.println("Dump of actJsonObject"); + JSONP_Util.dumpJsonObject(actJsonObject); + + System.out.println("Compare expJsonObject and actJsonObject for equality"); + pass = JSONP_Util.assertEqualsJsonObjects(expJsonObject, actJsonObject); + } catch (Exception e) { + throw new Fault("readObjectTest4 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readObjectTest4 Failed"); + } + + /* + * @testName: readObjectTest5 + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:181; + * JSONP:JAVADOC:420; JSONP:JAVADOC:449; + * + * @test_Strategy: Test read of an object from a resource file with lots of + * nesting. Use JsonReader.read() API call. Test scenario: Read InputStream of + * JSON text containing a JSON object from resource file with lots of nesting + * use UTF-8 encoding with empty configuration. Create a JsonWriter to write + * above JsonObject to a string of JSON text. Compare expected JSON text with + * actual JSON text for equality. Filter all text output to remove whitespace + * before comparison. + * + * Tests the following API's: JsonReader = + * Json.createReaderFactory(Map<String,?>).createReader(InputStream, Charset) + * JsonReader.read() JsonObject object = (JsonObject)JsonReader.read() + * + * + */ + @Test + public void readObjectTest5() throws Fault { + boolean pass = true; + JsonReader reader = null; + String resourceFile = "jsonObjectWithLotsOfNestedObjectsData.json"; + try { + System.out.println("Reading contents of resource file " + resourceFile); + String readerContents = JSONP_Util + .getContentsOfResourceAsString(resourceFile); + System.out.println("readerContents=" + readerContents); + + // Create expected JSON text from resource contents filtered of whitespace + // for comparison + System.out.println("Filter readerContents of whitespace for comparison"); + String expJsonText = JSONP_Util.removeWhitespace(readerContents); + + System.out.println( + "Read contents of InputStream from resource file: " + resourceFile); + reader = Json.createReaderFactory(JSONP_Util.getEmptyConfig()) + .createReader(JSONP_Util.getInputStreamFromResource(resourceFile), + JSONP_Util.UTF_8); + JsonObject myJsonObject = (JsonObject) reader.read(); + + System.out.println("Write the JsonObject 'myJsonObject' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeObject(myJsonObject); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String writerContents = sWriter.toString(); + + System.out.println("Dump contents of the JsonWriter as a String"); + System.out.println("writerContents=" + writerContents); + + System.out.println("Filter writerContents of whitespace for comparison"); + String actJsonText = JSONP_Util.removeWhitespace(writerContents); + + System.out.println("Compare actual JSON text with expected JSON text"); + pass = JSONP_Util.assertEqualsJsonText(expJsonText, actJsonText); + } catch (Exception e) { + throw new Fault("readObjectTest5 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readObjectTest5 Failed"); + } + + /* + * @testName: readObjectEncodingTest + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:420; JSONP:JAVADOC:185; + * JSONP:JAVADOC:449; + * + * @test_Strategy: Test read of a JsonObject from a resource file using both + * encodings of UTF-8 and UTF-16LE. + * + * Test scenario: For each encoding read the appropriate resource file + * containing a string value. Call JsonObject.getJsonString() to get the value + * of the JsonString. Compare expected string with actual string for equality. + */ + @Test + public void readObjectEncodingTest() throws Fault { + boolean pass = true; + JsonReader reader = null; + String expString = "a\u65e8\u452c\u8b9e\u6589\u5c57\u5217z"; + String resourceFileUTF8 = "jsonObjectUTF8.json"; + String resourceFileUTF16LE = "jsonObjectUTF16LE.json"; + try { + System.out.println("Reading contents of resource file using UTF-8 encoding " + + resourceFileUTF8); + InputStream is = JSONP_Util.getInputStreamFromResource(resourceFileUTF8); + Map<String, ?> config = JSONP_Util.getEmptyConfig(); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_8); + JsonObject jsonObject = reader.readObject(); + System.out.println("Comparing JsonObject values with expected results."); + String actString = jsonObject.getJsonString("unicodeChars").getString(); + if (!JSONP_Util.assertEquals(expString, actString)) + pass = false; + } catch (Exception e) { + throw new Fault("readObjectEncodingTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + try { + System.out.println("Reading contents of resource file using UTF-16LE encoding " + + resourceFileUTF16LE); + InputStream is = JSONP_Util + .getInputStreamFromResource(resourceFileUTF16LE); + Map<String, ?> config = JSONP_Util.getEmptyConfig(); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_16LE); + JsonObject jsonObject = reader.readObject(); + System.out.println("Comparing JsonObject values with expected results."); + String actString = jsonObject.getJsonString("unicodeChars").getString(); + if (!JSONP_Util.assertEquals(expString, actString)) + pass = false; + } catch (Exception e) { + throw new Fault("readObjectEncodingTest Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("readObjectEncodingTest Failed"); + } + + /* + * @testName: readUTFEncodedTests + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:420; JSONP:JAVADOC:185; + * JSONP:JAVADOC:449; + * + * @test_Strategy: Tests the JsonReader reader. Verifies READING of the + * JsonObject defined in resource files: + * + * jsonObjectEncodingUTF8.json jsonObjectEncodingUTF16.json + * jsonObjectEncodingUTF16LE.json jsonObjectEncodingUTF16BE.json + * jsonObjectEncodingUTF32LE.json jsonObjectEncodingUTF32BE.json + * + * Creates the JsonReader via the API: + * + * JsonReader reader = + * Json.createReaderFactory(Map<String,?>).createReader(InputStream, Charset) + * + * For each supported encoding supported by JSON RFC read the JsonObject and + * verify we get the expected results. The Charset encoding is passed in as + * argument for each encoding type read. + */ + @Test + public void readUTFEncodedTests() throws Fault { + boolean pass = true; + JsonReader reader = null; + Map<String, ?> config = JSONP_Util.getEmptyConfig(); + try { + System.out.println( + "-----------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createReaderFactory(Map<String,?>).createReader(InputStream, Charset) as UTF-8]"); + System.out.println( + "-----------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF8.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF8.json"); + System.out.println( + "Create JsonReader from the InputStream with character encoding UTF-8"); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_8); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-8 encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createReaderFactory(Map<String,?>).createReader(InputStream, Charset) as UTF-16]"); + System.out.println( + "------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16.json"); + System.out.println( + "Create JsonReader from the InputStream with character encoding UTF-16"); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_16); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-16 encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createReaderFactory(Map<String,?>).createReader(InputStream, Charset) as UTF-16LE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16LE.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16LE.json"); + System.out.println( + "Create JsonReader from the InputStream with character encoding UTF-16LE"); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_16LE); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-16LE encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createReaderFactory(Map<String,?>).createReader(InputStream, Charset) as UTF-16BE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16BE.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16BE.json"); + System.out.println( + "Create JsonReader from the InputStream with character encoding UTF-16BE"); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_16BE); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-16BE encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createReaderFactory(Map<String,?>).createReader(InputStream, Charset) as UTF-32LE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF32LE.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF32LE.json"); + System.out.println( + "Create JsonReader from the InputStream with character encoding UTF-32LE"); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_32LE); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-32LE encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createReaderFactory(Map<String,?>).createReader(InputStream, Charset) as UTF-32BE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF32BE.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF32BE.json"); + System.out.println( + "Create JsonReader from the InputStream with character encoding UTF-32BE"); + reader = Json.createReaderFactory(config).createReader(is, + JSONP_Util.UTF_32BE); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-32BE encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("readUTFEncodedTests Failed"); + } + + /* + * @testName: readUTFEncodedTests2 + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:178; JSONP:JAVADOC:185; + * + * @test_Strategy: Tests the JsonReader reader. Verifies READING of the + * JsonObject defined in resource files: + * + * jsonObjectEncodingUTF8.json jsonObjectEncodingUTF16LE.json + * jsonObjectEncodingUTF16BE.json jsonObjectEncodingUTF32LE.json + * jsonObjectEncodingUTF32BE.json + * + * Creates the JsonReader via the API: + * + * JsonReader reader = Json.createReader(InputStream istream) + * + * For each supported encoding supported by JSON RFC read the JsonObject and + * verify we get the expected results. The character encoding of the stream is + * auto-detected and determined as per the RFC. + */ + @Test + public void readUTFEncodedTests2() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + System.out.println("---------------------------------------------------"); + System.out.println("TEST CASE [Json.createReader(InputStream) as UTF-8]"); + System.out.println("---------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF8.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF8.json"); + System.out.println( + "Create JsonReader from the InputStream and auto-detect character encoding UTF-8"); + reader = Json.createReader(is); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-8 encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + try { + System.out.println("------------------------------------------------------"); + System.out.println("TEST CASE [Json.createReader(InputStream) as UTF-16LE]"); + System.out.println("------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16LE.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16LE.json"); + System.out.println( + "Create JsonReader from the InputStream and auto-detect character encoding UTF-16LE"); + reader = Json.createReader(is); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-16LE encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + try { + System.out.println("------------------------------------------------------"); + System.out.println("TEST CASE [Json.createReader(InputStream) as UTF-16BE]"); + System.out.println("------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF16BE.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF16BE.json"); + System.out.println( + "Create JsonReader from the InputStream and auto-detect character encoding UTF-16BE"); + reader = Json.createReader(is); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-16BE encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + try { + System.out.println("------------------------------------------------------"); + System.out.println("TEST CASE [Json.createReader(InputStream) as UTF-32LE]"); + System.out.println("------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF32LE.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF32LE.json"); + System.out.println( + "Create JsonReader from the InputStream and auto-detect character encoding UTF-32LE"); + reader = Json.createReader(is); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-32LE encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + try { + System.out.println("------------------------------------------------------"); + System.out.println("TEST CASE [Json.createReader(InputStream) as UTF-32BE]"); + System.out.println("------------------------------------------------------"); + System.out.println( + "Get InputStream from data file as resource (jsonObjectEncodingUTF32BE.json)"); + InputStream is = JSONP_Util + .getInputStreamFromResource("jsonObjectEncodingUTF32BE.json"); + System.out.println( + "Create JsonReader from the InputStream and auto-detect character encoding UTF-32BE"); + reader = Json.createReader(is); + JsonObject jsonObject = reader.readObject(); + if (!compareJsonObjectForUTFEncodedTests(jsonObject)) + pass = false; + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing reading of UTF-32BE encoding: " + e); + } finally { + try { + if (reader != null) + reader.close(); + } catch (Exception e) { + } + } + if (!pass) + throw new Fault("readUTFEncodedTests2 Failed"); + } + + /* + * @testName: negativeObjectTests + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:413; + * + * @test_Strategy: Test various Json Syntax Errors when reading a JsonObject. + * The tests trip various JsonParsingException/JsonException conditions when + * reading an object. + * + */ + @Test + public void negativeObjectTests() throws Fault { + boolean pass = true; + JsonReader reader = null; + + // Not an object [] + + try { + System.out.println("Testing for not an object '[]'"); + reader = Json.createReader(new StringReader("[]")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonException"); + } catch (JsonException e) { + System.out.println("Got expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Trip JsonParsingException for JsonReader.readObject() if incorrect + // representation for object + try { + System.out.println( + "Trip JsonParsingException for JsonReader.read() if incorrect representation for object."); + System.out.println("Reading " + "{\"name\":\"value\",1,2,3}"); + reader = Json + .createReader(new StringReader("{\"name\":\"value\",1,2,3}")); + JsonObject jsonObject = reader.readObject(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Missing [ + + try { + System.out.println("Testing for missing '['"); + reader = Json.createReader(new StringReader("{1,2]}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing ] + + try { + System.out.println("Testing for missing ']'"); + reader = Json.createReader(new StringReader("{[1,2}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing { + + try { + System.out.println("Testing for missing '{'"); + reader = Json.createReader(new StringReader("}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing } + + try { + System.out.println("Testing for missing '}'"); + reader = Json.createReader(new StringReader("{")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between array elements test case 1 + + try { + System.out.println("Testing for missing ',' between array elements test case 1"); + reader = Json.createReader(new StringReader("{[5\"foo\"]}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between array elements test case 2 + + try { + System.out.println("Testing for missing ',' between array elements test case 2"); + reader = Json.createReader(new StringReader("{[5{}]}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between object elements test case 1 + + try { + System.out.println("Testing for missing ',' between object elements test case 1"); + reader = Json.createReader(new StringReader("{\"foo\":\"bar\"5}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between object elements test case 2 + + try { + System.out.println("Testing for missing ',' between object elements test case 2"); + reader = Json.createReader(new StringReader("{\"one\":1[]}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing key name in object element + + try { + System.out.println("Testing for missing key name in object element"); + reader = Json.createReader(new StringReader("{:\"bar\"}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing value name in object element + + try { + System.out.println("Testing for missing value name in object element"); + reader = Json.createReader(new StringReader("{\"foo\":}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing double quote on a name + + try { + System.out.println("Test for missing double quote on a name"); + reader = Json.createReader(new StringReader("{name\" : \"value\"}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing double quote on a value + + try { + System.out.println("Test for missing double quote on a value"); + reader = Json.createReader(new StringReader("{\"name\" : value\"}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 1 + + try { + System.out.println("Incorrect digit value -foo"); + reader = Json.createReader(new StringReader("{\"number\" : -foo}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 2 + + try { + System.out.println("Incorrect digit value +foo"); + reader = Json.createReader(new StringReader("{\"number\" : +foo}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 3 + + try { + System.out.println("Incorrect digit value -784foo"); + reader = Json.createReader(new StringReader("{\"number\" : -784foo}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 4 + + try { + System.out.println("Incorrect digit value +784foo"); + reader = Json.createReader(new StringReader("{\"number\" : +784foo}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 5 + + try { + System.out.println("Incorrect digit value 0.1E5E5"); + reader = Json.createReader(new StringReader("{\"number\" : 0.1E5E5}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 6 + + try { + System.out.println("Incorrect digit value 0.F10"); + reader = Json.createReader(new StringReader("{\"number\" : 0.F10}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 7 + + try { + System.out.println("Incorrect digit value string"); + reader = Json.createReader(new StringReader("{\"number\" : string}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 8 (hex numbers invalid per JSON RFC) + + try { + System.out.println("Incorrect digit value hex numbers invalid per JSON RFC"); + reader = Json.createReader(new StringReader("{\"number\" : 0x137a}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 9 (octal numbers invalid per JSON RFC) + + try { + System.out.println("Incorrect digit value octal numbers invalid per JSON RFC"); + reader = Json.createReader(new StringReader("{\"number\" : 0137}")); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + if (!pass) + throw new Fault("negativeObjectTests Failed"); + } + + /* + * @testName: negativeArrayTests + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:412; + * + * @test_Strategy: Test various Json Syntax Errors when reading a JsonArray. + * The tests trip various JsonParsingException/JsonException conditions when + * reading an array. + * + */ + @Test + public void negativeArrayTests() throws Fault { + boolean pass = true; + JsonReader reader = null; + + // Not an array {} + + try { + System.out.println("Testing for not an array '{}'"); + reader = Json.createReader(new StringReader("{}")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonException"); + } catch (JsonException e) { + System.out.println("Got expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Trip JsonParsingException for JsonReader.readArray() if incorrect + // representation for array + try { + System.out.println( + "Trip JsonParsingException for JsonReader.readArray() if incorrect representation for array."); + System.out.println("Reading " + "[foo,10,\"name\":\"value\"]"); + reader = Json + .createReader(new StringReader("[foo,10,\"name\":\"value\"]")); + JsonArray jsonArray = reader.readArray(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Missing [ + + try { + System.out.println("Testing for missing '['"); + reader = Json.createReader(new StringReader("]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing ] + + try { + System.out.println("Testing for missing ']'"); + reader = Json.createReader(new StringReader("[")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing { + + try { + System.out.println("Testing for missing '{'"); + reader = Json.createReader(new StringReader("[1,\"name\":\"value\"}]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing } + + try { + System.out.println("Testing for missing '}'"); + reader = Json.createReader(new StringReader("[1,{\"name\":\"value\"]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between array elements test case 1 + + try { + System.out.println("Testing for missing ',' between array elements test case 1"); + reader = Json.createReader(new StringReader("[5\"foo\"]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between array elements test case 2 + + try { + System.out.println("Testing for missing ',' between array elements test case 2"); + reader = Json.createReader(new StringReader("[5{}]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between object elements test case 1 + + try { + System.out.println("Testing for missing ',' between object elements test case 1"); + reader = Json.createReader(new StringReader("[{\"foo\":\"bar\"5}]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between object elements test case 2 + + try { + System.out.println("Testing for missing ',' between object elements test case 2"); + reader = Json.createReader(new StringReader("[{\"one\":1[]}]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing key name in object element + + try { + System.out.println("Testing for missing key name in object element"); + reader = Json.createReader(new StringReader("[{:\"bar\"}]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing value name in object element + + try { + System.out.println("Testing for missing value name in object element"); + reader = Json.createReader(new StringReader("[{\"foo\":}]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing double quote on a name + + try { + System.out.println("Test for missing double quote on a name"); + reader = Json.createReader(new StringReader("[{name\" : \"value\"}]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing double quote on a value + + try { + System.out.println("Test for missing double quote on a value"); + reader = Json.createReader(new StringReader("[{\"name\" : value\"}]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 1 + + try { + System.out.println("Incorrect digit value -foo"); + reader = Json.createReader(new StringReader("[-foo]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 2 + + try { + System.out.println("Incorrect digit value +foo"); + reader = Json.createReader(new StringReader("[+foo]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 3 + + try { + System.out.println("Incorrect digit value -784foo"); + reader = Json.createReader(new StringReader("[-784foo]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 4 + + try { + System.out.println("Incorrect digit value +784foo"); + reader = Json.createReader(new StringReader("[+784foo]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 5 + + try { + System.out.println("Incorrect digit value 0.1E5E5"); + reader = Json.createReader(new StringReader("[0.1E5E5]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 6 + + try { + System.out.println("Incorrect digit value 0.F10"); + reader = Json.createReader(new StringReader("[0.F10]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 7 + + try { + System.out.println("Incorrect digit value string"); + reader = Json.createReader(new StringReader("[string]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 8 (hex numbers invalid per JSON RFC) + + try { + System.out.println("Incorrect digit value hex numbers invalid per JSON RFC"); + reader = Json.createReader(new StringReader("[0x137a]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 9 (octal numbers invalid per JSON RFC) + + try { + System.out.println("Incorrect digit value octal numbers invalid per JSON RFC"); + reader = Json.createReader(new StringReader("[0137]")); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + if (!pass) + throw new Fault("negativeArrayTests Failed"); + } + + /* + * @testName: illegalStateExceptionTests + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:218; + * JSONP:JAVADOC:220; JSONP:JAVADOC:183; + * + * @test_Strategy: Test IllegalStateException test conditions. + * + */ + @Test + public void illegalStateExceptionTests() throws Fault { + boolean pass = true; + JsonReader reader = null; + + // IllegalStateException if reader.close() called before reader.read() + try { + reader = Json.createReader(new StringReader("{}")); + reader.close(); + System.out.println( + "Calling reader.read() after reader.close() is called is illegal."); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // IllegalStateException if reader.read() called after reader.readObject() + try { + reader = Json.createReader(new StringReader("{}")); + JsonObject value = reader.readObject(); + System.out.println( + "Calling reader.readObject() after reader.readObject() was called is illegal."); + value = (JsonObject) reader.read(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // IllegalStateException if reader.read() called after reader.readArray() + try { + reader = Json.createReader(new StringReader("[]")); + JsonArray value = reader.readArray(); + System.out.println( + "Calling reader.read() after reader.readArray() was called is illegal."); + value = (JsonArray) reader.read(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // IllegalStateException if reader.close() called before reader.readObject() + try { + reader = Json.createReader(new StringReader("{}")); + reader.close(); + System.out.println( + "Calling reader.readObject() after reader.close() is called is illegal."); + JsonObject value = reader.readObject(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // IllegalStateException if reader.readObject() called after + // reader.readObject() + try { + reader = Json.createReader(new StringReader("{}")); + JsonObject value = reader.readObject(); + System.out.println( + "Calling reader.readObject() after reader.readObject() was called is illegal."); + value = reader.readObject(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // IllegalStateException if reader.readArray() called after + // reader.readObject() + try { + reader = Json.createReader(new StringReader("{}")); + JsonObject obj = reader.readObject(); + System.out.println( + "Calling reader.readArray() after reader.readObject() was called is illegal."); + JsonArray arr = reader.readArray(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // IllegalStateException if reader.close() called before reader.readArray() + try { + reader = Json.createReader(new StringReader("[]")); + reader.close(); + System.out.println( + "Calling reader.readArray() after reader.close() is called is illegal."); + JsonArray value = reader.readArray(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // IllegalStateException if reader.readArray() called after + // reader.readArray() + try { + reader = Json.createReader(new StringReader("[]")); + JsonArray value = reader.readArray(); + System.out.println( + "Calling reader.readArray() after reader.readArray() was called is illegal."); + value = reader.readArray(); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // IllegalStateException if reader.readObject() called after + // reader.readArray() + try { + reader = Json.createReader(new StringReader("[]")); + JsonArray arr = reader.readArray(); + System.out.println( + "Calling reader.readObject() after reader.readArray() was called is illegal."); + JsonObject obj = reader.readObject(); + pass = false; + System.out.println("obj=" + obj); + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + if (!pass) + throw new Fault("illegalStateExceptionTests Failed"); + } + + /* + * @testName: negativeJsonStructureTests + * + * @assertion_ids: JSONP:JAVADOC:96; JSONP:JAVADOC:97; JSONP:JAVADOC:411; + * + * @test_Strategy: Test various Json Syntax Errors when reading a + * JsonStructure. The tests trip various JsonParsingException conditions when + * doing a read. + * + */ + @Test + public void negativeJsonStructureTests() throws Fault { + boolean pass = true; + JsonReader reader = null; + + // Trip JsonParsingException for JsonReader.read() if incorrect + // representation for array + try { + System.out.println( + "Trip JsonParsingException for JsonReader.read() if incorrect representation for array."); + System.out.println("Reading " + "[foo,10,\"name\":\"value\"]"); + reader = Json + .createReader(new StringReader("[foo,10,\"name\":\"value\"]")); + JsonStructure jsonStructure = reader.read(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonParsingException for JsonReader.read() if incorrect + // representation for object + try { + System.out.println( + "Trip JsonParsingException for JsonReader.read() if incorrect representation for object."); + System.out.println("Reading " + "{\"name\":\"value\",1,2,3}"); + reader = Json + .createReader(new StringReader("{\"name\":\"value\",1,2,3}")); + JsonStructure jsonStructure = reader.read(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // incorrect representation {] + try { + System.out.println("Testing for incorrect representation '{]'"); + reader = Json.createReader(new StringReader("{]")); + System.out.println( + "Calling reader.read() with incorrect representation should throw JsonParsingException"); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Missing [ + + try { + System.out.println("Testing for missing '['"); + reader = Json.createReader(new StringReader("{1,2]}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing ] + + try { + System.out.println("Testing for missing ']'"); + reader = Json.createReader(new StringReader("{[1,2}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing { + + try { + System.out.println("Testing for missing '{'"); + reader = Json.createReader(new StringReader("}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing } + + try { + System.out.println("Testing for missing '}'"); + reader = Json.createReader(new StringReader("{")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between array elements test case 1 + + try { + System.out.println("Testing for missing ',' between array elements test case 1"); + reader = Json.createReader(new StringReader("{[5\"foo\"]}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between array elements test case 2 + + try { + System.out.println("Testing for missing ',' between array elements test case 2"); + reader = Json.createReader(new StringReader("{[5{}]}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between object elements test case 1 + + try { + System.out.println("Testing for missing ',' between object elements test case 1"); + reader = Json.createReader(new StringReader("{\"foo\":\"bar\"5}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing , between object elements test case 2 + + try { + System.out.println("Testing for missing ',' between object elements test case 2"); + reader = Json.createReader(new StringReader("{\"one\":1[]}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing key name in object element + + try { + System.out.println("Testing for missing key name in object element"); + reader = Json.createReader(new StringReader("{:\"bar\"}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing value name in object element + + try { + System.out.println("Testing for missing value name in object element"); + reader = Json.createReader(new StringReader("{\"foo\":}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing double quote on a name + + try { + System.out.println("Test for missing double quote on a name"); + reader = Json.createReader(new StringReader("{name\" : \"value\"}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Missing double quote on a value + + try { + System.out.println("Test for missing double quote on a value"); + reader = Json.createReader(new StringReader("{\"name\" : value\"}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 1 + + try { + System.out.println("Incorrect digit value -foo"); + reader = Json.createReader(new StringReader("{\"number\" : -foo}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 2 + + try { + System.out.println("Incorrect digit value +foo"); + reader = Json.createReader(new StringReader("{\"number\" : +foo}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 3 + + try { + System.out.println("Incorrect digit value -784foo"); + reader = Json.createReader(new StringReader("{\"number\" : -784foo}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 4 + + try { + System.out.println("Incorrect digit value +784foo"); + reader = Json.createReader(new StringReader("{\"number\" : +784foo}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 5 + + try { + System.out.println("Incorrect digit value 0.1E5E5"); + reader = Json.createReader(new StringReader("{\"number\" : 0.1E5E5}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 6 + + try { + System.out.println("Incorrect digit value 0.F10"); + reader = Json.createReader(new StringReader("{\"number\" : 0.F10}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + // Incorrect digit value test case 7 + + try { + System.out.println("Incorrect digit value string"); + reader = Json.createReader(new StringReader("{\"number\" : string}")); + JsonStructure value = reader.read(); + pass = false; + System.err.println("Failed to throw JsonParsingException"); + } catch (JsonParsingException e) { + System.out.println("Got expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (reader != null) + reader.close(); + } + + if (!pass) + throw new Fault("negativeJsonStructureTests Failed"); + } + + /* + * @testName: jsonReaderIOErrorTests + * + * @assertion_ids: JSONP:JAVADOC:182; JSONP:JAVADOC:217; JSONP:JAVADOC:219; + * JSONP:JAVADOC:410; + * + * @test_Strategy: Tests for JsonException for testable i/o errors. + * + */ + @Test + public void jsonReaderIOErrorTests() throws Fault { + boolean pass = true; + + String jsonArrayText = "[\"name1\",\"value1\"]"; + String jsonObjectText = "{\"name1\":\"value1\"}"; + + // Trip JsonException if there is an i/o error on JsonReader.close() + try { + System.out.println( + "Trip JsonException if there is an i/o error on JsonReader.close()."); + System.out.println("Reading object " + jsonObjectText); + InputStream is = JSONP_Util.getInputStreamFromString(jsonObjectText); + MyBufferedInputStream mbi = new MyBufferedInputStream(is); + try (JsonReader reader = Json.createReader(mbi)) { + JsonObject jsonObject = reader.readObject(); + System.out.println("jsonObject=" + jsonObject); + mbi.setThrowIOException(true); + System.out.println("Calling JsonReader.close()"); + mbi.setThrowIOException(true); + } + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonException for JsonReader.read() if i/o error + try { + System.out.println("Trip JsonException for JsonReader.read() if i/o error."); + System.out.println("Reading array " + jsonArrayText); + MyBufferedReader mbr = new MyBufferedReader( + new StringReader(jsonArrayText)); + JsonReader reader = Json.createReader(mbr); + mbr.setThrowIOException(true); + System.out.println("Calling JsonReader.read()"); + JsonStructure jsonStructure = reader.read(); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonException for JsonReader.readArray() if i/o error + try { + System.out.println("Trip JsonException for JsonReader.readArray() if i/o error."); + System.out.println("Reading array " + jsonArrayText); + MyBufferedReader mbr = new MyBufferedReader( + new StringReader(jsonArrayText)); + JsonReader reader = Json.createReader(mbr); + mbr.setThrowIOException(true); + System.out.println("Calling JsonReader.readArray()"); + JsonArray jsonArray = reader.readArray(); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonException for JsonReader.readObject() if i/o error + try { + System.out.println("Trip JsonException for JsonReader.read() if i/o error."); + System.out.println("Reading object " + jsonObjectText); + MyBufferedReader mbr = new MyBufferedReader( + new StringReader(jsonObjectText)); + JsonReader reader = Json.createReader(mbr); + mbr.setThrowIOException(true); + System.out.println("Calling JsonReader.readObject()"); + JsonObject jsonObject = reader.readObject(); + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonReaderIOErrorTests Failed"); + } + + /* + * @testName: invalidLiteralNamesTest + * + * @assertion_ids: JSONP:JAVADOC:97; JSONP:JAVADOC:411; + * + * @test_Strategy: This test trips various JsonParsingException conditions + * when reading an uppercase literal name that must be lowercase per JSON RFC + * for the literal values (true, false or null). + * + */ + @Test + public void invalidLiteralNamesTest() throws Fault { + boolean pass = true; + JsonReader reader; + + // Trip JsonParsingException for JsonReader.read() if invalid liternal TRUE + // instead of true + try { + System.out.println( + "Trip JsonParsingException for JsonReader.read() if invalid liternal TRUE instead of true."); + System.out.println("Reading " + "[TRUE]"); + reader = Json.createReader(new StringReader("[TRUE]")); + JsonStructure jsonStructure = reader.read(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonParsingException for JsonReader.read() if invalid liternal FALSE + // instead of false + try { + System.out.println( + "Trip JsonParsingException for JsonReader.read() if invalid liternal FALSE instead of false."); + System.out.println("Reading " + "[FALSE]"); + reader = Json.createReader(new StringReader("[FALSE]")); + JsonStructure jsonStructure = reader.read(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonParsingException for JsonReader.read() if invalid liternal NULL + // instead of null + try { + System.out.println( + "Trip JsonParsingException for JsonReader.read() if invalid liternal NULL instead of null."); + System.out.println("Reading " + "[NULL]"); + reader = Json.createReader(new StringReader("[NULL]")); + JsonStructure jsonStructure = reader.read(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonParsingException for JsonReader.read() if invalid liternal TRUE + // instead of true + try { + System.out.println( + "Trip JsonParsingException for JsonReader.read() if invalid liternal TRUE instead of true."); + System.out.println("Reading " + "{\"true\":TRUE}"); + reader = Json.createReader(new StringReader("{\"true\":TRUE}")); + JsonStructure jsonStructure = reader.read(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonParsingException for JsonReader.read() if invalid liternal FALSE + // instead of false + try { + System.out.println( + "Trip JsonParsingException for JsonReader.read() if invalid liternal FALSE instead of false."); + System.out.println("Reading " + "{\"false\":FALSE}"); + reader = Json.createReader(new StringReader("{\"false\":FALSE}")); + JsonStructure jsonStructure = reader.read(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonParsingException for JsonReader.read() if invalid liternal NULL + // instead of null + try { + System.out.println( + "Trip JsonParsingException for JsonReader.read() if invalid liternal NULL instead of null."); + System.out.println("Reading " + "{\"null\":NULL}"); + reader = Json.createReader(new StringReader("{\"null\":NULL}")); + JsonStructure jsonStructure = reader.read(); + System.err.println("Did not get expected JsonParsingException"); + pass = false; + } catch (JsonParsingException e) { + System.out.println("Caught expected JsonParsingException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("invalidLiteralNamesTest Failed"); + } + + /* + * @testName: jsonReader11Test + * + * @assertion_ids: JSONP:JAVADOC:646; JSONP:JAVADOC:583; JSONP:JAVADOC:584; + * JSONP:JAVADOC:585; JSONP:JAVADOC:586; JSONP:JAVADOC:587; JSONP:JAVADOC:588; + * JSONP:JAVADOC:662; JSONP:JAVADOC:663; JSONP:JAVADOC:664; JSONP:JAVADOC:665; + * JSONP:JAVADOC:666; JSONP:JAVADOC:667; + * + * @test_Strategy: Tests JsonReader API methods added in JSON-P 1.1. + */ + @Test + public void jsonReader11Test() throws Fault { + Reader readerTest = new Reader(); + final TestResult result = readerTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonreadertests/Reader.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonreadertests/Reader.java new file mode 100644 index 0000000..e400ca2 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonreadertests/Reader.java
@@ -0,0 +1,235 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonreadertests; + +import jakarta.jsonp.tck.api.common.JsonValueType; +import jakarta.jsonp.tck.api.common.SimpleValues; +import jakarta.jsonp.tck.api.common.TestResult; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringReader; +import jakarta.json.Json; +import jakarta.json.JsonException; +import jakarta.json.JsonReader; +import jakarta.json.JsonValue; +import jakarta.json.stream.JsonParsingException; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests for {@link JsonReader}. + */ +public class Reader { + + /** Tests input data. */ + private static final Object[] VALUES = new Object[] { OBJ_VALUE, // readValue() + // for + // JsonObject + createEmptyArrayWithStr(), // readValue() for simple JsonArray + STR_VALUE, // readValue() for String + INT_VALUE, // readValue() for int + LNG_VALUE, // readValue() for long + DBL_VALUE, // readValue() for double + BIN_VALUE, // readValue() for BigInteger + BDC_VALUE, // readValue() for BigDecimal + BOOL_VALUE, // readValue() for boolean + null // readValue() for null + }; + + /** + * Creates an instance of JavaScript Object Notation (JSON) compatibility + * tests for {@link JsonReader}. + */ + Reader() { + super(); + } + + /** + * {@link JsonReader} API methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonReader API methods added in JSON-P 1.1."); + System.out.println("JsonReader API methods added in JSON-P 1.1."); + testReadValue(result); + testDoubleReadValue(result); + testIOExceptionOnReadValue(result); + testReadInvalidValue(result); + return result; + } + + /** + * Test {@code JsonValue readValue()} method on all child types stored in + * source data. + * + * @param result + * Test suite result. + */ + private void testReadValue(final TestResult result) { + for (Object value : VALUES) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println(" - readValue() for " + typeName + " in source data"); + final JsonValue jsonValue = SimpleValues.toJsonValue(value); + final String data = JsonValueType.toStringValue(value); + System.out.println(" - Data: " + data); + final StringReader strReader = new StringReader(data); + JsonValue outValue = null; + try (final JsonReader reader = Json.createReader(strReader)) { + outValue = reader.readValue(); + } catch (JsonException ex) { + System.out.println("Caught JsonException: " + ex.getLocalizedMessage()); + result.fail("readValue()", + "Caught JsonException: " + ex.getLocalizedMessage()); + } + if (operationFailed(jsonValue, outValue)) { + result.fail("readValue()", "Reader output " + valueToString(outValue) + + " value shall be " + valueToString(jsonValue)); + } + } + } + + /** + * Test {@code JsonValue readValue()} method with duplicated {@code JsonValue} + * read call. Second call is expected to throw {@code IllegalStateException} + * exception. + * + * @param result + * Test suite result. + */ + private void testDoubleReadValue(final TestResult result) { + for (Object value : VALUES) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println( + " - duplicate readValue() for " + typeName + " in source data"); + final String data = JsonValueType.toStringValue(value); + final StringReader strReader = new StringReader(data); + try (final JsonReader reader = Json.createReader(strReader)) { + // 1st attempt to read the data shall pass + reader.readValue(); + try { + // 2nd attempt to read the data shall throw IllegalStateException + reader.readValue(); + result.fail("readValue()", + "Duplicate call of readValue() shall throw IllegalStateException"); + } catch (IllegalStateException ex) { + System.out.println(" - Expected exception: " + ex.getMessage()); + } catch (Throwable t) { + result.fail("readValue()", + "Duplicate call of readValue() shall throw IllegalStateException, not " + + t.getClass().getSimpleName()); + } + } catch (JsonException ex) { + System.out.println("Caught JsonException: " + ex.getLocalizedMessage()); + result.fail("readValue()", + "Caught JsonException: " + ex.getLocalizedMessage()); + } + } + } + + /** + * Test {@code JsonValue readValue()} method with read call that causes + * IOException. IOException shall be encapsulated in JsonException. + * + * @param result + * Test suite result. + */ + @SuppressWarnings("ConvertToTryWithResources") + private void testIOExceptionOnReadValue(final TestResult result) { + System.out.println(" - readValue() from already closed file reader"); + File temp = null; + JsonReader reader; + // Close writer before calling write method. + try { + temp = File.createTempFile("testIOExceptionOnReadValue", ".txt"); + System.out.println(" - Temporary file: " + temp.getAbsolutePath()); + try (final FileWriter fileWriter = new FileWriter(temp)) { + fileWriter.write(JsonValueType.toStringValue(DEF_VALUE)); + } + final FileReader fileReader = new FileReader(temp); + reader = Json.createReader(fileReader); + fileReader.close(); + } catch (IOException ex) { + System.out.println("Caught IOException: " + ex.getLocalizedMessage()); + result.fail("write(JsonValue)", + "Caught IOException: " + ex.getLocalizedMessage()); + return; + } finally { + if (temp != null) { + temp.delete(); + } + } + try { + reader.readValue(); + result.fail("readValue()", + "Call of readValue() on already closed file reader shall throw JsonException"); + } catch (JsonException ex) { + System.out.println(" - Expected exception: " + ex.getMessage()); + } catch (Throwable t) { + result.fail("readValue()", + "Call of readValue() on already closed file reader shall throw JsonException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Test {@code JsonValue readValue()} method with read call on invalid JSON + * data. JsonParsingException shall be thrown when reading invalid data. + * + * @param result + * Test suite result. + */ + private void testReadInvalidValue(final TestResult result) { + System.out.println(" - readValue() on invalid JSON data"); + // Invalid JSON: starting an array, closing an object. + final String data = "[" + SimpleValues.toJsonValue(DEF_VALUE) + "}"; + final StringReader strReader = new StringReader(data); + JsonValue outValue = null; + try (final JsonReader reader = Json.createReader(strReader)) { + reader.readValue(); + result.fail("readValue()", + "Call of readValue() on invalid data shall throw JsonParsingException"); + } catch (JsonParsingException ex) { + System.out.println(" - Expected exception: " + ex.getMessage()); + } catch (Throwable t) { + result.fail("readValue()", + "Call of readValue() on invalid data shall throw JsonParsingException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonstreamingtests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonstreamingtests/ClientTests.java new file mode 100644 index 0000000..188e46d --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonstreamingtests/ClientTests.java
@@ -0,0 +1,286 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonstreamingtests; + +import jakarta.json.*; +import jakarta.json.stream.*; + +import java.io.*; +import java.util.*; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* + * @testName: streamingTest1 + * + * @assertion_ids: JSONP:JAVADOC:97; JSONP:JAVADOC:106; JSONP:JAVADOC:107; + * JSONP:JAVADOC:184; + * + * @test_Strategy: Test Scenario: Generate stream of Json Text containing a + * JsonArray Compare actual Json Text generated with expected Json Text for + * equality Test passes if both JsonArray comparisons of Json Text are equal. + * + */ + @Test + public void streamingTest1() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + // Set expected result + String expJsonText = "[1,2,3,4,5,6,7,8,9,10]"; + System.out.println("expJsonText=" + expJsonText); + + System.out.println("Generate stream of Json Text containing a JsonArray"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write(1).write(2).write(3).write(4).write(5) + .write(6).write(7).write(8).write(9).write(10).writeEnd(); + generator.close(); + + // Get actual result + String actJsonText = JSONP_Util.removeWhitespace(sWriter.toString()); + System.out.println("actJsonText=" + actJsonText); + + System.out.println("Compare expJsonText and actJsonText for equality"); + pass = JSONP_Util.assertEqualsJsonText(expJsonText, actJsonText); + } catch (Exception e) { + throw new Fault("streamingTest1 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("streamingTest1 Failed"); + } + + /* + * @testName: streamingTest2 + * + * @assertion_ids: JSONP:JAVADOC:97; JSONP:JAVADOC:106; JSONP:JAVADOC:107; + * JSONP:JAVADOC:131; + * + * @test_Strategy: Test Scenario: Generate data containing a JsonArray to a + * Writer stream. Read data from Writer stream containing a JsonArray. Write + * JsonArray out to a Writer stream. Re-read data from Writer stream + * containing a JsonArray. Compare initial JsonArray with subsequent JsonArray + * for equality. Test passes if both JsonArrays are equal. + * + */ + @Test + public void streamingTest2() throws Fault { + boolean pass = true; + JsonReader reader = null; + try { + System.out.println("Generate data containing a JsonArray"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartArray().write(2).write(4).write(6).write(8).write(10) + .writeEnd(); + generator.close(); + + System.out.println("Read data from Writer stream containing a JsonArray"); + reader = Json.createReader(new StringReader(sWriter.toString())); + JsonArray expJsonArray = reader.readArray(); + + System.out.println("Dump of expJsonArray"); + JSONP_Util.dumpJsonArray(expJsonArray); + + System.out.println("Write JsonArray out to a Writer stream"); + sWriter = new StringWriter(); + JsonWriter writer = Json.createWriter(sWriter); + writer.writeArray(expJsonArray); + System.out.println("Close JsonWriter"); + writer.close(); + + System.out.println("Save contents of the JsonWriter as a String"); + String writerContents = sWriter.toString(); + System.out.println("writerContents=" + writerContents); + + System.out.println("Re-read data from Writer stream containing a JsonArray"); + reader = Json.createReader(new StringReader(writerContents)); + JsonArray actJsonArray = reader.readArray(); + + System.out.println("Dump of actJsonArray"); + JSONP_Util.dumpJsonArray(actJsonArray); + + System.out.println("Compare expJsonArray and actJsonArray for equality"); + pass = JSONP_Util.assertEqualsJsonArrays(expJsonArray, actJsonArray); + } catch (Exception e) { + throw new Fault("streamingTest2 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("streamingTest2 Failed"); + } + + /* + * @testName: streamingTest3 + * + * @assertion_ids: JSONP:JAVADOC:97; JSONP:JAVADOC:106; JSONP:JAVADOC:110; + * JSONP:JAVADOC:131; JSONP:JAVADOC:172; + * + * @test_Strategy: Test Scenario: Generate data containing a JsonObject to a + * Write stream. Read data from Writer stream containing a JsonObject. Write + * JsonObject out to a Writer stream. Parse data from Writer stream containing + * a JsonObject stream. Test passes if parsing JsonObject events are correct. + * + */ + @Test + public void streamingTest3() throws Fault { + boolean pass = true; + JsonReader reader = null; + JsonParser parser = null; + try { + System.out.println("Generate data containing a JsonObject"); + StringWriter sWriter = new StringWriter(); + JsonGenerator generator = Json.createGenerator(sWriter); + generator.writeStartObject().write("two", 2).write("false", false) + .writeEnd(); + generator.close(); + + System.out.println("Read data from Writer stream containing a JsonObject"); + reader = Json.createReader(new StringReader(sWriter.toString())); + JsonObject expJsonObject = reader.readObject(); + + System.out.println("Dump of expJsonObject"); + JSONP_Util.dumpJsonObject(expJsonObject); + + System.out.println("Write JsonObject out to a Writer stream"); + sWriter = new StringWriter(); + JsonWriter writer = Json.createWriter(sWriter); + writer.writeObject(expJsonObject); + System.out.println("Close JsonWriter"); + writer.close(); + + System.out.println("Save contents of the JsonWriter as a String"); + String writerContents = sWriter.toString(); + System.out.println("writerContents=" + writerContents); + + System.out.println("Parse data from Writer stream containing a JsonObject"); + parser = Json + .createParser(JSONP_Util.getInputStreamFromString((writerContents))); + + JSONP_Util.resetParseErrs(); + JSONP_Util.testEventType(parser, JsonParser.Event.START_OBJECT); + JSONP_Util.testKeyIntegerValue(parser, "two", 2); + JSONP_Util.testKeyFalseValue(parser, "false"); + JSONP_Util.testEventType(parser, JsonParser.Event.END_OBJECT); + int parseErrs = JSONP_Util.getParseErrs(); + if (parseErrs != 0) { + System.err.println("There were " + parseErrs + " parser errors that occurred."); + pass = false; + } + + } catch (Exception e) { + throw new Fault("streamingTest3 Failed: ", e); + } finally { + if (reader != null) + reader.close(); + } + if (!pass) + throw new Fault("streamingTest3 Failed"); + } + + /* + * @testName: streamingTest4 + * + * @assertion_ids: JSONP:JAVADOC:178; JSONP:JAVADOC:187; JSONP:JAVADOC:110; + * JSONP:JAVADOC:168; + * + * @test_Strategy: Test Scenario: Generate data containing a JsonObject to an + * OutputStream. Compare expected JSON text from what was generated. Read data + * from InputStream containing a JsonObject. Write JsonObject again out to an + * OutputStream. Compare again expected JSON text from what was generated. + * Test passes if JSON text comparisons are correct. + * + */ + @Test + public void streamingTest4() throws Fault { + boolean pass = true; + JsonReader reader = null; + JsonParser parser = null; + String expJsonText = "{\"two\":2,\"false\":false}"; + try { + System.out.println("Generate data containing a JsonObject to an OutputStream"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonGenerator generator = Json.createGenerator(baos); + generator.writeStartObject().write("two", 2).write("false", false) + .writeEnd(); + baos.close(); + generator.close(); + + System.out.println("Compare JSON text generated to what is expected."); + if (!JSONP_Util.assertEqualsJsonText(expJsonText, + JSONP_Util.removeWhitespace(baos.toString("UTF-8")))) + pass = false; + + System.out.println("Read data from InputStream containing a JsonObject"); + reader = Json.createReader( + JSONP_Util.getInputStreamFromString(baos.toString("UTF-8"))); + JsonObject expJsonObject = reader.readObject(); + System.out.println("Close JsonReader"); + reader.close(); + + System.out.println("Dump of expJsonObject"); + JSONP_Util.dumpJsonObject(expJsonObject); + + System.out.println("Write JsonObject back out to an OutputStream"); + baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriter(baos); + writer.writeObject(expJsonObject); + System.out.println("Close JsonWriter"); + baos.close(); + writer.close(); + + System.out.println("Save contents of the JsonWriter as a String"); + String writerContents = baos.toString("UTF-8"); + System.out.println("writerContents=" + writerContents); + + System.out.println("Compare again JSON text generated to what is expected."); + if (!JSONP_Util.assertEqualsJsonText(expJsonText, + JSONP_Util.removeWhitespace(writerContents))) + pass = false; + + } catch (Exception e) { + throw new Fault("streamingTest4 Failed: ", e); + } + + if (!pass) + throw new Fault("streamingTest4 Failed"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonstringtests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonstringtests/ClientTests.java new file mode 100644 index 0000000..06672ca --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonstringtests/ClientTests.java
@@ -0,0 +1,201 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonstringtests; + +import jakarta.json.*; +import jakarta.json.stream.*; + +import java.io.*; + +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; +import java.math.BigDecimal; +import java.math.BigInteger; + +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonStringEqualsTest + * + * @assertion_ids: JSONP:JAVADOC:254; + * + * @test_Strategy: Tests JsonString equals method. Create 2 equal JsonStrings + * and compare them for equality and expect true. Create 2 non-equal + * JsonStrings and compare them for equality and expect false. + */ + @Test + public void jsonStringEqualsTest() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonString 1 for testing"); + JsonString string1 = (JsonString) JSONP_Util + .createJsonString("Hello World"); + System.out.println("string1=" + JSONP_Util.toStringJsonString(string1)); + + System.out.println("Create sample JsonString 2 for testing"); + JsonString string2 = JSONP_Util.createJsonString("Hello World"); + System.out.println("string2=" + JSONP_Util.toStringJsonString(string2)); + + System.out.println( + "Call JsonString.equals() to compare 2 equal JsonStrings and expect true"); + if (string1.equals(string2)) { + System.out.println("JsonStrings are equal - expected."); + } else { + pass = false; + System.err.println("JsonStrings are not equal - unexpected."); + } + + System.out.println("Create sample JsonString 1 for testing"); + string1 = JSONP_Util.createJsonString("Hello World"); + System.out.println("string1=" + JSONP_Util.toStringJsonString(string1)); + + System.out.println("Create sample JsonString 2 for testing"); + string2 = JSONP_Util.createJsonString("Hello USA"); + System.out.println("string2=" + JSONP_Util.toStringJsonString(string2)); + + System.out.println( + "Call JsonString.equals() to compare 2 equal JsonStrings and expect false"); + if (!string1.equals(string2)) { + System.out.println("JsonStrings are not equal - expected."); + } else { + pass = false; + System.err.println("JsonStrings are equal - unexpected."); + } + } catch (Exception e) { + throw new Fault("jsonStringEqualsTest Failed: ", e); + } + if (!pass) + throw new Fault("jsonStringEqualsTest Failed"); + } + + /* + * @testName: jsonStringHashCodeTest + * + * @assertion_ids: JSONP:JAVADOC:255; + * + * @test_Strategy: Tests JsonString equals method. Create 2 equal JsonStrings + * and compare them for hashcode and expect true. Create 2 non-equal + * JsonStrings and compare them for hashcode and expect false. + */ + @Test + public void jsonStringHashCodeTest() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonString 1 for testing"); + JsonString string1 = JSONP_Util.createJsonString("Hello World"); + System.out.println("string1=" + JSONP_Util.toStringJsonString(string1)); + System.out.println("string1.hashCode()=" + string1.hashCode()); + + System.out.println("Create sample JsonString 2 for testing"); + JsonString string2 = JSONP_Util.createJsonString("Hello World"); + System.out.println("string2=" + JSONP_Util.toStringJsonString(string2)); + System.out.println("string2.hashCode()=" + string2.hashCode()); + + System.out.println( + "Call JsonString.hashCode() to compare 2 equal JsonStrings and expect true"); + if (string1.hashCode() == string2.hashCode()) { + System.out.println("JsonStrings hashCode are equal - expected."); + } else { + pass = false; + System.err.println("JsonStrings hashCode are not equal - unexpected."); + } + + System.out.println("Create sample JsonString 1 for testing"); + string1 = JSONP_Util.createJsonString("Hello World"); + System.out.println("string1=" + JSONP_Util.toStringJsonString(string1)); + System.out.println("string1.hashCode()=" + string1.hashCode()); + + System.out.println("Create sample JsonString 2 for testing"); + string2 = JSONP_Util.createJsonString("Hello USA"); + System.out.println("string2=" + JSONP_Util.toStringJsonString(string2)); + System.out.println("string2.hashCode()=" + string2.hashCode()); + + System.out.println( + "Call JsonString.hashCode() to compare 2 equal JsonStrings and expect false"); + if (string1.hashCode() != string2.hashCode()) { + System.out.println("JsonStrings hashCode are not equal - expected."); + } else { + pass = false; + System.err.println("JsonStrings hashCode are equal - unexpected."); + } + } catch (Exception e) { + throw new Fault("jsonStringHashCodeTest Failed: ", e); + } + if (!pass) + throw new Fault("jsonStringHashCodeTest Failed"); + } + + /* + * @testName: jsonStringGetCharsTest + * + * @assertion_ids: JSONP:JAVADOC:383; + * + * @test_Strategy: Tests JsonString getChars method. + */ + @Test + public void jsonStringGetCharsTest() throws Fault { + boolean pass = true; + String helloWorld = "Hello World"; + + try { + System.out.println("Create sample JsonString for testing"); + JsonString string = JSONP_Util.createJsonString(helloWorld); + System.out.println("string=" + JSONP_Util.toStringJsonString(string)); + + System.out.println( + "Call JsonString.getChars() to return the char sequence for the JSON string"); + CharSequence cs = string.getChars(); + System.out.println("charSequence=" + cs.toString()); + + System.out.println("Checking char sequence for equality to expected string contents"); + if (!JSONP_Util.assertEquals(helloWorld, cs.toString())) + pass = false; + + System.out.println("Checking char sequence for expected equality to string length"); + if (!JSONP_Util.assertEquals(helloWorld.length(), cs.length())) + pass = false; + } catch (Exception e) { + throw new Fault("jsonStringGetCharsTest Failed: ", e); + } + if (!pass) + throw new Fault("jsonStringGetCharsTest Failed"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonvaluetests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonvaluetests/ClientTests.java new file mode 100644 index 0000000..7f60a54 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonvaluetests/ClientTests.java
@@ -0,0 +1,354 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonvaluetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +import java.util.*; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.json.*; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonValueTypesTest + * + * @assertion_ids: JSONP:JAVADOC:102; + * + * @test_Strategy: Test JsonValue.getValueType() API method call with all + * JsonValue types. + * + */ + @Test + public void jsonValueTypesTest() throws Fault { + boolean pass = true; + try { + + JsonValue.ValueType valueType; + + // Testing JsonValue.FALSE case + System.out.println("Testing getValueType for JsonValue.FALSE value"); + valueType = JsonValue.FALSE.getValueType(); + if (valueType != JsonValue.ValueType.FALSE) { + System.err.println("Expected JSON FALSE value type but got instead " + valueType); + pass = false; + } else + System.out.println("Got expected value type for JSON FALSE value"); + + // Testing JsonValue.TRUE case + System.out.println("Testing getValueType for JsonValue.TRUE value"); + valueType = JsonValue.TRUE.getValueType(); + if (valueType != JsonValue.ValueType.TRUE) { + System.err.println("Expected JSON TRUE value type but got instead " + valueType); + pass = false; + } else + System.out.println("Got expected value type for JSON TRUE value"); + + // Testing JsonValue.NULL case + System.out.println("Testing getValueType for JsonValue.NULL value"); + valueType = JsonValue.NULL.getValueType(); + if (valueType != JsonValue.ValueType.NULL) { + System.err.println("Expected JSON NULL value type but got instead " + valueType); + pass = false; + } else + System.out.println("Got expected value type for JSON NULL value"); + + // Testing JsonValue.String case + System.out.println("Testing getValueType for JsonValue.String value"); + valueType = JSONP_Util.createJsonString("string").getValueType(); + if (valueType != JsonValue.ValueType.STRING) { + System.err.println("Expected JSON STRING value type but got instead " + valueType); + pass = false; + } else + System.out.println("Got expected value type for JSON STRING value"); + + // Testing JsonValue.Number case + System.out.println("Testing getValueType for JsonValue.Number value"); + valueType = JSONP_Util.createJsonNumber(Integer.MAX_VALUE).getValueType(); + if (valueType != JsonValue.ValueType.NUMBER) { + System.err.println("Expected JSON NUMBER value type but got instead " + valueType); + pass = false; + } else + System.out.println("Got expected value type for JSON NUMBER value"); + + // Testing JsonValue.Array case + System.out.println("Testing getValueType for JsonValue.Array value"); + valueType = JSONP_Util.createJsonArrayFromString("[]").getValueType(); + if (valueType != JsonValue.ValueType.ARRAY) { + System.err.println("Expected JSON ARRAY value type but got instead " + valueType); + pass = false; + } else + System.out.println("Got expected value type for JSON ARRAY value"); + + // Testing JsonValue.Object case + System.out.println("Testing getValueType for JsonValue.Object value"); + valueType = JSONP_Util.createJsonObjectFromString("{}").getValueType(); + if (valueType != JsonValue.ValueType.OBJECT) { + System.err.println("Expected JSON OBJECT value type but got instead " + valueType); + pass = false; + } else + System.out.println("Got expected value type for JSON OBJECT value"); + + } catch (Exception e) { + throw new Fault("jsonValueTypesTest Failed: ", e); + } + if (!pass) + throw new Fault("jsonValueTypesTest Failed"); + } + + /* + * @testName: jsonValueOfTest + * + * @assertion_ids: JSONP:JAVADOC:103; + * + * @test_Strategy: Test JsonValue.ValueType.valueOf() API method call with all + * JsonValue types. + * + */ + @Test + public void jsonValueOfTest() throws Fault { + boolean pass = true; + + String valueTypeStrings[] = { "ARRAY", "FALSE", "NULL", "NUMBER", "OBJECT", + "STRING", "TRUE" }; + + for (String valueTypeString : valueTypeStrings) { + JsonValue.ValueType valueType; + try { + System.out.println( + "Testing enum value for string constant name " + valueTypeString); + valueType = JsonValue.ValueType.valueOf(valueTypeString); + System.out.println("Got enum type " + valueType + " for enum string constant named " + + valueTypeString); + } catch (Exception e) { + System.err.println("Caught unexpected exception: " + e); + pass = false; + } + + } + + System.out.println("Testing negative test case for NullPointerException"); + try { + JsonValue.ValueType.valueOf(null); + System.err.println("did not get expected NullPointerException"); + pass = false; + } catch (NullPointerException e) { + System.out.println("Got expected NullPointerException"); + } catch (Exception e) { + System.err.println("Got unexpected exception " + e); + pass = false; + } + + System.out.println("Testing negative test case for IllegalArgumentException"); + try { + JsonValue.ValueType.valueOf("INVALID"); + System.err.println("did not get expected IllegalArgumentException"); + pass = false; + } catch (IllegalArgumentException e) { + System.out.println("Got expected IllegalArgumentException"); + } catch (Exception e) { + System.err.println("Got unexpected exception " + e); + pass = false; + } + + if (!pass) + throw new Fault("jsonValueOfTest Failed"); + } + + /* + * @testName: jsonValuesTest + * + * @assertion_ids: JSONP:JAVADOC:104; + * + * @test_Strategy: Test JsonValue.ValueType.values() API method call and + * verify enums returned. + * + */ + @Test + public void jsonValuesTest() throws Fault { + boolean pass = true; + + System.out.println( + "Testing API method JsonValue.ValueType.values() to return array of enums."); + JsonValue.ValueType[] values = JsonValue.ValueType.values(); + + for (JsonValue.ValueType valueType : values) { + String valueString = JSONP_Util.getValueTypeString(valueType); + if (valueString == null) { + System.err.println("Got no value for enum " + valueType); + pass = false; + } else + System.out.println("Got " + valueString + " for enum " + valueType); + } + + if (!pass) + throw new Fault("jsonValuesTest Failed"); + } + + /* + * @testName: jsonValueToStringTest + * + * @assertion_ids: JSONP:JAVADOC:288; + * + * @test_Strategy: Test JsonValue.toString() API method call with various + * JsonValue types. + * + */ + @Test + public void jsonValueToStringTest() throws Fault { + boolean pass = true; + try { + String stringValue; + JsonValue jsonValue; + + // Testing JsonValue.FALSE case + System.out.println("Testing JsonValue.toString() for JsonValue.FALSE value"); + stringValue = JsonValue.FALSE.toString(); + System.out.println("stringValue=" + stringValue); + if (!stringValue.equals("false")) { + System.err.println("Expected false"); + pass = false; + } else { + System.out.println("Got " + stringValue); + } + + // Testing JsonValue.TRUE case + System.out.println("Testing JsonValue.toString() for JsonValue.TRUE value"); + stringValue = JsonValue.TRUE.toString(); + System.out.println("stringValue=" + stringValue); + if (!stringValue.equals("true")) { + System.err.println("Expected true"); + pass = false; + } else { + System.out.println("Got " + stringValue); + } + + // Testing JsonValue.NULL case + System.out.println("Testing JsonValue.toString() for JsonValue.NULL value"); + stringValue = JsonValue.NULL.toString(); + System.out.println("stringValue=" + stringValue); + if (!stringValue.equals("null")) { + System.err.println("Expected null"); + pass = false; + } else { + System.out.println("Got " + stringValue); + } + + // Testing JsonString case + System.out.println("Testing JsonValue.toString() for JsonString value"); + jsonValue = JSONP_Util.createJsonString("string"); + stringValue = jsonValue.toString(); + System.out.println("stringValue=" + stringValue); + if (!stringValue.equals("\"string\"")) { + System.err.println("Expected \"string\""); + pass = false; + } else { + System.out.println("Got " + stringValue); + } + + // Testing JsonNumber case + System.out.println("Testing JsonValue.toString() for JsonNumber value"); + jsonValue = JSONP_Util.createJsonNumber(10); + stringValue = jsonValue.toString(); + System.out.println("stringValue=" + stringValue); + if (!stringValue.equals("10")) { + System.err.println("Expected 10"); + pass = false; + } else { + System.out.println("Got " + stringValue); + } + + // Testing JsonArray case + System.out.println("Testing JsonValue.toString() for JsonArray value"); + jsonValue = JSONP_Util.createJsonArrayFromString("[]"); + stringValue = jsonValue.toString(); + System.out.println("stringValue=" + stringValue); + if (!stringValue.equals("[]")) { + System.err.println("Expected []"); + pass = false; + } else { + System.out.println("Got " + stringValue); + } + + // Testing JsonObject case + System.out.println("Testing JsonValue.toString() for JsonObject value"); + jsonValue = JSONP_Util.createJsonObjectFromString("{}"); + stringValue = jsonValue.toString(); + System.out.println("stringValue=" + stringValue); + if (!stringValue.equals("{}")) { + System.err.println("Expected {}"); + pass = false; + } else { + System.out.println("Got " + stringValue); + } + + } catch (Exception e) { + throw new Fault("jsonValueToStringTest Failed: ", e); + } + if (!pass) + throw new Fault("jsonValueToStringTest Failed"); + } + + /* + * @testName: jsonValue11Test + * + * @assertion_ids: JSONP:JAVADOC:648; JSONP:JAVADOC:649; + * + * @test_Strategy: Tests JsonValue API methods added in JSON-P 1.1. + */ + @Test + public void jsonValue11Test() throws Fault { + Value valueTest = new Value(); + final TestResult result = valueTest.test(); + result.eval(); + } + + /* + * @testName: jsonStructure11Test + * + * @assertion_ids: JSONP:JAVADOC:647; + * + * @test_Strategy: Tests JsonStructure API methods added in JSON-P 1.1. + */ + @Test + public void jsonStructure11Test() throws Fault { + Structure structTest = new Structure(); + final TestResult result = structTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonvaluetests/Structure.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonvaluetests/Structure.java new file mode 100644 index 0000000..629dd3e --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonvaluetests/Structure.java
@@ -0,0 +1,485 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonvaluetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.PointerRFCObject.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests for + * {@link JsonStructure}. RFC 6901 JSON Pointer is being passed to + * {@code JsonValue getValue(String)} method so whole JSON Pointer resolving + * sample is being used to test this method. + */ +public class Structure { + /** + * Creates an instance of JavaScript Object Notation (JSON) compatibility + * tests for {@link JsonStructure}. + */ + Structure() { + super(); + } + + /** + * {@link JsonStructure} API methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonStructure API methods added in JSON-P 1.1."); + System.out.println("JsonStructure API methods added in JSON-P 1.1."); + testResolveWholeDocument(result); + testResolveEmptyName(result); + testResolveSimpleArray(result); + testResolveSimpleArrayItems(result); + testResolvePathWithEncodedSlash(result); + testResolvePathWithSlash(result); + testResolvePathWithPercent(result); + testResolvePathWithCaret(result); + testResolvePathWithVerticalBar(result); + testResolvePathWithBackSlash(result); + testResolvePathWithDoubleQuotes(result); + testResolvePathWithSpace(result); + testResolvePathWithTilde(result); + testResolvePathWithEncodedTilde(result); + testResolvePathWithEncodedTildeOne(result); + testResolveValidNumericIndexInArray(result); + testResolveMemberAfterLastInArray(result); + testResolveNonNumericIndexInArray(result); + return result; + } + + /** + * Test RFC 6901 JSON Pointer resolving for the whole document path using + * {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolveWholeDocument(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = value; + verifyGetValue(result, check, value, RFC_KEY_WHOLE); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "": 0} using + * {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolveEmptyName(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL2); + verifyGetValue(result, check, value, RFC_PTR2); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "foo": ["bar", "baz"]} using + * {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolveSimpleArray(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = RFC_VAL1; + verifyGetValue(result, check, value, RFC_PTR1); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "foo": ["bar", "baz"]} array + * elements using {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolveSimpleArrayItems(final TestResult result) { + final String[] itemPtrs = new String[] { RFC_PTR1_ITEM1, RFC_PTR1_ITEM2 }; + final String[] itemVals = new String[] { RFC_VAL1_ITEM1, RFC_VAL1_ITEM2 }; + final JsonObject value = createRFC6901Object(); + for (int i = 0; i < itemPtrs.length; i++) { + final JsonValue check = Json.createValue(itemVals[i]); + verifyGetValue(result, check, value, itemPtrs[i]); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "a/b": 1} using + * {@code JsonValue getValue(String)}. Character {@code '/'} is encoded as + * {@code "~1"} string. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithEncodedSlash(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL3); + verifyGetValue(result, check, value, RFC_PTR3_ENC); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "a/b": 1} using + * {@code JsonValue getValue(String)}. Character {@code '/'} is not encoded as + * {@code "~1"} string. This results in invalid {@code "/a/b"} path and + * resolving such path must throw an exception. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithSlash(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + verifyGetValueFail(result, value, RFC_PTR3); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "c%d": 2} using + * {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithPercent(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL4); + verifyGetValue(result, check, value, RFC_PTR4); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "e^f": 3} using + * {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithCaret(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL5); + verifyGetValue(result, check, value, RFC_PTR5); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "g|h": 4} using + * {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithVerticalBar(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL6); + verifyGetValue(result, check, value, RFC_PTR6); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "i\\j": 5} using + * {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithBackSlash(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL7); + verifyGetValue(result, check, value, RFC_PTR7); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "k\"l": 6} using + * {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithDoubleQuotes(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL8); + verifyGetValue(result, check, value, RFC_PTR8); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code " ": 7} using + * {@code JsonValue getValue(String)}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithSpace(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL9); + verifyGetValue(result, check, value, RFC_PTR9); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "m~n": 8} without encoding + * using {@code JsonValue getValue(String)}. Passing this test is not + * mandatory. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-3">RFC 6901: 3. + * Syntax</a>} defines JSON pointer grammar as:<br> + * {@code json-pointer = *( "/" reference-token )}<br> + * {@code reference-token = *( unescaped / escaped )}<br> + * {@code unescaped = %x00-2E / %x30-7D / %x7F-10FFFF}<br> + * {@code escaped = "~" ( "0" / "1" )}<br> + * Characters {@code '/'} and {@code '~'} are excluded from {@code unescaped}. + * But having {@code '~'} outside escape sequence may be acceptable. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithTilde(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR10 + "\" pointer (optional)"); + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL10); + boolean noError = true; + try { + final JsonValue out = value.getValue(RFC_PTR10); + if (operationFailed(check, out)) { + noError = false; + System.out.println(" - Pointer \"" + RFC_KEY10 + + "\" did not return expected value"); + } + } catch (JsonException e) { + noError = false; + System.out.println(" - Expected exception: " + e.getMessage()); + } + if (noError) { + System.out.println( + " - Pointer resolving accepts '~' outside escape sequence"); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "m~n": 8} using + * {@code JsonValue getValue(String)}. Character {@code '~'} is encoded as + * {@code "~0"} string. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithEncodedTilde(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL10); + verifyGetValue(result, check, value, RFC_KEY10_ENC); + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "o~1p": 9} using + * {@code JsonValue getValue(String)}. String {@code "~1"} is encoded as + * {@code "~01"} String. Proper encoded sequences transformation is described + * in chapter: + * {@code "the string '~01' correctly becomes '~1' after transformation"}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithEncodedTildeOne(final TestResult result) { + final JsonStructure value = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL11); + verifyGetValue(result, check, value, RFC_PTR11_ENC); + } + + /** + * Test RFC 6901 JSON Pointer resolver for existing numeric indexes of an + * array. {@see <a href="https://tools.ietf.org/html/rfc6901#section-4">RFC + * 6901: 4. Evaluation</a>} chapter:<br> + * If the currently referenced value is a JSON array, the reference token MUST + * contain either: + * <ul> + * <li>characters comprised of digits (see ABNF below; note that leading zeros + * are not allowed) that represent an unsigned base-10 integer value, making + * the new referenced value the array element with the zero-based index + * identified by the token</li> + * </ul> + */ + private void testResolveValidNumericIndexInArray(final TestResult result) { + System.out.println( + " - getValue(String) resolving of pointer containing existing numeric array index"); + final JsonArray[] arraysIn = new JsonArray[] { createSimpleStringArray5(), + createSimpleIntArray5(), createSimpleBoolArray5(), + createSimpleObjectArray5() }; + final JsonValue[] strings = new JsonValue[] { toJsonValue(STR_VALUE_1), + toJsonValue(STR_VALUE_2), toJsonValue(STR_VALUE_3), + toJsonValue(STR_VALUE_4), toJsonValue(STR_VALUE_5) }; + final JsonValue[] ints = new JsonValue[] { toJsonValue(INT_VALUE_1), + toJsonValue(INT_VALUE_2), toJsonValue(INT_VALUE_3), + toJsonValue(INT_VALUE_4), toJsonValue(INT_VALUE_5) }; + final JsonValue[] bools = new JsonValue[] { toJsonValue(BOOL_FALSE), + toJsonValue(BOOL_TRUE), toJsonValue(BOOL_TRUE), toJsonValue(BOOL_FALSE), + toJsonValue(BOOL_TRUE) }; + final JsonValue[] objs = new JsonValue[] { OBJ_VALUE_1, OBJ_VALUE_2, + OBJ_VALUE_3, OBJ_VALUE_4, OBJ_VALUE_5 }; + final JsonValue[][] checks = new JsonValue[][] { strings, ints, bools, + objs }; + // Go trough all array types + for (int i = 0; i < arraysIn.length; i++) { + // Go trough all valid indexes in arrays + for (int j = 0; j < 5; j++) { + final String path = "/" + Integer.toString(j); + try { + final JsonValue out = arraysIn[i].getValue(path); + if (operationFailed(checks[i][j], out)) { + result.fail("getValue(String)", "Failed for \"" + path + "\" path"); + } + } catch (JsonException e) { + result.fail("getValue(String)", "Exception: " + e.getMessage()); + } + } + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for character {@code '-'} marking the + * end of an array. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-4">RFC 6901: 4. + * Evaluation</a>} chapter:<br> + * If the currently referenced value is a JSON array, the reference token MUST + * contain either: + * <ul> + * <li>exactly the single character "-", making the new referenced value the + * (nonexistent) member after the last array element</li> + * </ul> + * Note that the use of the "-" character to index an array will always result + * in such an error condition because by definition it refers to a nonexistent + * array element. Thus, applications of JSON Pointer need to specify how that + * character is to be handled, if it is to be useful. + */ + private void testResolveMemberAfterLastInArray(final TestResult result) { + System.out.println(" - getValue(String) resolving of array \"/-\" pointer"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray(), createSimpleIntArray5(), createBoolArray2(), + createSimpleObjectArray5() }; + for (int i = 0; i < arraysIn.length; i++) { + try { + arraysIn[i].getValue("/-"); + result.fail("getValue(String)", "Call of getValue(String) on \"" + "/-" + + "\" shall throw JsonException"); + } catch (JsonException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for invalid index containing non + * numeric characters on array. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-4">RFC 6901: 4. + * Evaluation</a>} chapter:<br> + * {@code array-index = %x30 / ( %x31-39 *(%x30-39) )} grammar rule prohibits + * indexes with anything else than sequence of digits. Index {@code '-'} is + * being checked in another tests. The only exception is path for whole + * document ({@code ""}) which must return the whole array. + */ + private void testResolveNonNumericIndexInArray(final TestResult result) { + System.out.println( + " - getValue(String) resolving of pointer containing non numeric array index"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray(), createSimpleIntArray5(), createBoolArray2(), + createSimpleObjectArray5() }; + final String[] typeNames = new String[] { "empty", "String", "int", + "boolean", "JsonObject" }; + final String wholeDocument = ""; + final String[] paths = new String[] { "/", "/1a", "/b4", "/name" }; + // Go trough all array types + for (int i = 0; i < arraysIn.length; i++) { + try { + final JsonValue wholeOut = arraysIn[i].getValue(wholeDocument); + if (operationFailed(wholeOut, arraysIn[i])) { + result.fail("getValue(String)", "Failed for \"" + wholeDocument + + "\" path on " + typeNames[i] + " array"); + } + } catch (JsonException e) { + result.fail("getValue(String)", "Failed for \"" + wholeDocument + + "\" path on " + typeNames[i] + " array: " + e.getMessage()); + } + for (int j = 0; j < paths.length; j++) { + try { + final JsonValue out = arraysIn[i].getValue(paths[j]); + result.fail("getValue(String)", "Succeeded for \"" + paths[j] + + "\" path on " + typeNames[i] + " array"); + } catch (JsonException e) { + // There are too many combinations to log them. + } + } + } + } + + /** + * Test helper: Verify {@code JsonValue getValue(String)} for given JSON path. + * + * @param result + * Tests result record. + */ + private void verifyGetValue(final TestResult result, final JsonValue check, + final JsonStructure value, final String path) { + System.out.println(" - getValue(String) resolving of \"" + path + "\" pointer"); + try { + final JsonValue out = value.getValue(path); + if (operationFailed(check, out)) { + result.fail("getValue(String)", "Failed for \"" + path + "\" path"); + } + } catch (JsonException e) { + result.fail("getValue(String)", "Exception: " + e.getMessage()); + } + } + + /** + * Test helper: Verify {@code JsonValue getValue(String)} for given JSON path. + * + * @param result + * Tests result record. + */ + private void verifyGetValueFail(final TestResult result, + final JsonStructure value, final String path) { + System.out.println( + " - getValue(String) resolving of invalid \"" + path + "\" pointer"); + try { + value.getValue(path); + result.fail("getValue(String)", "Call of getValue(String) on \"" + path + + "\" shall throw JsonException"); + } catch (JsonException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonvaluetests/Value.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonvaluetests/Value.java new file mode 100644 index 0000000..29e5179 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonvaluetests/Value.java
@@ -0,0 +1,178 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonvaluetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests for {@link JsonValue}. + */ +public class Value { + + /** + * Creates an instance of JavaScript Object Notation (JSON) compatibility + * tests for {@link JsonValue}. + */ + Value() { + super(); + } + + /** + * {@link JsonValue} API methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonValue API methods added in JSON-P 1.1."); + System.out.println("JsonValue API methods added in JSON-P 1.1."); + testAsJsonObject(result); + testAsJsonObjectOnNonObject(result); + testAsJsonArray(result); + testAsJsonArrayOnNonArray(result); + return result; + } + + /** + * Test {@code JsonObject asJsonObject()} method on {@code JsonObject} + * instances. + * + * @param result + * Test suite result. + */ + private void testAsJsonObject(final TestResult result) { + System.out.println(" - asJsonObject() on JsonObject instances"); + final JsonObject[] values = { createEmptyObject(), createSimpleObjectStr(), + createSimpleObjectInt(), createSimpleObjectBool(), + createSimpleObjectObject(), createCompoundObject() }; + for (final JsonObject objValue : values) { + final JsonValue value = objValue; + final JsonObject out = objValue.asJsonObject(); + if (operationFailed(objValue, out)) { + result.fail("asJsonObject()", "Output " + valueToString(out) + + " value shall be " + valueToString(objValue)); + } + } + } + + /** + * Test {@code JsonObject asJsonObject()} method on non {@code JsonObject} + * instances. + * + * @param result + * Test suite result. + */ + private void testAsJsonObjectOnNonObject(final TestResult result) { + System.out.println(" - asJsonObject() on non JsonObject instances"); + final JsonValue[] values = { createEmptyArrayWithStr(), + createEmptyArrayWithInt(), createEmptyArrayWithBool(), + createEmptyArrayWithObject(), toJsonValue(STR_VALUE), + toJsonValue(INT_VALUE), toJsonValue(LNG_VALUE), toJsonValue(DBL_VALUE), + toJsonValue(BIN_VALUE), toJsonValue(BDC_VALUE), toJsonValue(BOOL_VALUE), + toJsonValue(null) }; + for (final JsonValue value : values) { + try { + value.asJsonObject(); + result.fail("asJsonObject()", + "Call of asJsonObject() on non JsonObject instance shall throw ClassCastException"); + } catch (ClassCastException ex) { + System.out.println(" - Expected exception: " + ex.getMessage()); + } catch (Throwable t) { + result.fail("asJsonObject()", + "Call of asJsonObject() on non JsonObject instance shall throw ClassCastException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Test {@code JsonObject asJsonArray()} method on {@code JsonArray} + * instances. + * + * @param result + * Test suite result. + */ + private void testAsJsonArray(final TestResult result) { + System.out.println(" - asJsonArray() on JsonArray instances"); + final JsonArray[] values = { createEmptyArray(), createEmptyArrayWithStr(), + createEmptyArrayWithInt(), createEmptyArrayWithBool(), + createEmptyArrayWithObject(), createSimpleStringArray5(), + createSimpleIntArray5(), createSimpleBoolArray5(), + createSimpleObjectArray5() }; + for (final JsonArray objValue : values) { + final JsonValue value = objValue; + final JsonArray out = objValue.asJsonArray(); + if (operationFailed(objValue, out)) { + result.fail("asJsonArray()", "Output " + valueToString(out) + + " value shall be " + valueToString(objValue)); + } + } + } + + /** + * Test {@code JsonObject asJsonArray()} method on non {@code JsonArray} + * instances. + * + * @param result + * Test suite result. + */ + private void testAsJsonArrayOnNonArray(final TestResult result) { + System.out.println(" - asJsonArray() on non JsonArray instances"); + final JsonValue[] values = { createSimpleObjectStr(), + createSimpleObjectInt(), createSimpleObjectBool(), + createSimpleObjectObject(), createCompoundObject(), + toJsonValue(STR_VALUE), toJsonValue(INT_VALUE), toJsonValue(LNG_VALUE), + toJsonValue(DBL_VALUE), toJsonValue(BIN_VALUE), toJsonValue(BDC_VALUE), + toJsonValue(BOOL_VALUE), toJsonValue(null) }; + for (final JsonValue value : values) { + try { + value.asJsonArray(); + result.fail("asJsonArray()", + "Call of asJsonArray() on non JsonArray instance shall throw ClassCastException"); + } catch (ClassCastException ex) { + System.out.println(" - Expected exception: " + ex.getMessage()); + } catch (Throwable t) { + result.fail("asJsonArray()", + "Call of asJsonArray() on non JsonArray instance shall throw ClassCastException, not " + + t.getClass().getSimpleName()); + } + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonwriterfactorytests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonwriterfactorytests/ClientTests.java new file mode 100644 index 0000000..875bbe1 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonwriterfactorytests/ClientTests.java
@@ -0,0 +1,324 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/* + * $Id$ + */ +package jakarta.jsonp.tck.api.jsonwriterfactorytests; + +import jakarta.json.*; +import jakarta.json.stream.*; + +import java.io.*; +import java.nio.charset.Charset; + +import java.util.Properties; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; +import java.util.Iterator; +import java.util.Map; +import java.util.ArrayList; + +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonWriterFactoryTest1 + * + * @assertion_ids: JSONP:JAVADOC:110; JSONP:JAVADOC:414; JSONP:JAVADOC:422; + * JSONP:JAVADOC:452; JSONP:JAVADOC:463; + * + * @test_Strategy: Tests the JsonWriterFactory API. + * + * JsonWriterFactory writerFactory = Json.createWriterFactory(Map<String, ?>); + * JsonWriter writer1 = writerFactory.createWriter(Writer) JsonWriter writer2 + * = writerFactory.createWriter(Writer) + */ + @Test + public void jsonWriterFactoryTest1() throws Fault { + boolean pass = true; + JsonWriter writer1 = null; + JsonWriter writer2 = null; + String expString = "{}"; + String actString; + JsonObject jsonObject = Json.createReader(new StringReader(expString)) + .readObject(); + try { + System.out.println("Create JsonWriterFactory with Map<String, ?> with EMPTY config"); + JsonWriterFactory writerFactory = Json + .createWriterFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = writerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + System.out.println("--------------------------------------------------"); + System.out.println("TEST CASE [JsonWriterFactory.createWriter(Writer)]"); + System.out.println("--------------------------------------------------"); + System.out.println("Create 1st JsonWriter using JsonWriterFactory"); + Writer sWriter1 = new StringWriter(); + writer1 = writerFactory.createWriter(sWriter1); + if (writer1 == null) { + System.err.println("WriterFactory failed to create writer1"); + pass = false; + } else { + writer1.writeObject(jsonObject); + writer1.close(); + } + System.out.println("sWriter1=" + sWriter1.toString()); + actString = JSONP_Util.removeWhitespace(sWriter1.toString()); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + System.out.println("Create 2nd JsonWriter using JsonWriterFactory"); + Writer sWriter2 = new StringWriter(); + writer2 = writerFactory.createWriter(sWriter2); + if (writer2 == null) { + System.err.println("WriterFactory failed to create writer2"); + pass = false; + } else { + writer2.writeObject(jsonObject); + writer2.close(); + } + System.out.println("sWriter2=" + sWriter2.toString()); + actString = JSONP_Util.removeWhitespace(sWriter2.toString()); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonWriterFactoryTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterFactoryTest1 Failed"); + } + + /* + * @testName: jsonWriterFactoryTest2 + * + * @assertion_ids: JSONP:JAVADOC:110; JSONP:JAVADOC:414; JSONP:JAVADOC:424; + * JSONP:JAVADOC:452; JSONP:JAVADOC:463; + * + * @test_Strategy: Tests the JsonWriterFactory API. + * + * JsonWriterFactory writerFactory = Json.createWriterFactory(Map<String,?>); + * JsonWriter writer1 = writerFactory.createWriter(OutputStream, Charset) + * JsonWriter writer2 = writerFactory.createWriter(OutputStream, Charset) + * + * Create writer with both UTF-8 and UTF-16BE. + */ + @Test + public void jsonWriterFactoryTest2() throws Fault { + boolean pass = true; + JsonWriter writer1 = null; + JsonWriter writer2 = null; + String expString = "{}"; + String actString; + JsonObject jsonObject = Json.createReader(new StringReader(expString)) + .readObject(); + try { + System.out.println("Create JsonWriterFactory with Map<String, ?> with EMPTY config"); + JsonWriterFactory writerFactory = Json + .createWriterFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = writerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println( + "-----------------------------------------------------------------"); + System.out.println( + "TEST CASE [JsonWriterFactory.createWriter(OutputStream, Charset)]"); + System.out.println( + "-----------------------------------------------------------------"); + System.out.println( + "Create 1st JsonWriter using JsonWriterFactory with UTF-8 encoding"); + ByteArrayOutputStream baos1 = new ByteArrayOutputStream(); + writer1 = writerFactory.createWriter(baos1, JSONP_Util.UTF_8); + if (writer1 == null) { + System.err.println("WriterFactory failed to create writer1"); + pass = false; + } else { + writer1.writeObject(jsonObject); + writer1.close(); + } + System.out.println("baos1=" + baos1.toString("UTF-8")); + actString = JSONP_Util.removeWhitespace(baos1.toString("UTF-8")); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + System.out.println( + "Create 2nd JsonWriter using JsonWriterFactory with UTF-8 encoding"); + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + writer2 = writerFactory.createWriter(baos2, JSONP_Util.UTF_8); + if (writer2 == null) { + System.err.println("WriterFactory failed to create writer2"); + pass = false; + } else { + writer2.writeObject(jsonObject); + writer2.close(); + } + System.out.println("baos2=" + baos2.toString("UTF-8")); + actString = JSONP_Util.removeWhitespace(baos2.toString("UTF-8")); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonWriterFactoryTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterFactoryTest2 Failed"); + } + + /* + * @testName: jsonWriterFactoryTest3 + * + * @assertion_ids: JSONP:JAVADOC:110; JSONP:JAVADOC:414; JSONP:JAVADOC:423; + * JSONP:JAVADOC:452; JSONP:JAVADOC:463; + * + * @test_Strategy: Tests the JsonWriterFactory API. + * + * JsonWriterFactory writerFactory = Json.createWriterFactory(Map<String,?>); + * JsonWriter writer1 = writerFactory.createWriter(OutputStream) JsonWriter + * writer2 = writerFactory.createWriter(OutputStream) + */ + @Test + public void jsonWriterFactoryTest3() throws Fault { + boolean pass = true; + JsonWriter writer1 = null; + JsonWriter writer2 = null; + String expString = "{}"; + String actString; + JsonObject jsonObject = Json.createReader(new StringReader(expString)) + .readObject(); + try { + System.out.println("Create JsonWriterFactory with Map<String, ?> with EMPTY config"); + JsonWriterFactory writerFactory = Json + .createWriterFactory(JSONP_Util.getEmptyConfig()); + System.out.println("Checking factory configuration properties"); + Map<String, ?> config = writerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("--------------------------------------------------------"); + System.out.println("TEST CASE [JsonWriterFactory.createWriter(OutputStream)]"); + System.out.println("--------------------------------------------------------"); + System.out.println("Create 1st JsonWriter using JsonWriterFactory"); + ByteArrayOutputStream baos1 = new ByteArrayOutputStream(); + writer1 = writerFactory.createWriter(baos1); + if (writer1 == null) { + System.err.println("WriterFactory failed to create writer1"); + pass = false; + } else { + writer1.writeObject(jsonObject); + writer1.close(); + } + System.out.println("baos1=" + baos1.toString("UTF-8")); + actString = JSONP_Util.removeWhitespace(baos1.toString("UTF-8")); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + System.out.println("Create 2nd JsonWriter using JsonWriterFactory"); + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + writer2 = writerFactory.createWriter(baos2); + if (writer2 == null) { + System.err.println("WriterFactory failed to create writer2"); + pass = false; + } else { + writer2.writeObject(jsonObject); + writer2.close(); + } + System.out.println("baos2=" + baos2.toString("UTF-8")); + actString = JSONP_Util.removeWhitespace(baos2.toString("UTF-8")); + if (!JSONP_Util.assertEqualsJsonText(expString, actString)) + pass = false; + + } catch (Exception e) { + throw new Fault("jsonWriterFactoryTest3 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterFactoryTest3 Failed"); + } + + /* + * @testName: jsonWriterFactoryTest4 + * + * @assertion_ids: JSONP:JAVADOC:452; JSONP:JAVADOC:463; + * + * @test_Strategy: Tests the JsonWriterFactory API. + * + * JsonWriterFactory writerFactory = Json.createWriterFactory(Map<String, ?>); + * Map<String, ?> config = JsonWriterFactory.getConfigInUse(); + * + * Test for the following 3 scenarios: 1) no supported provider property + * (empty config) 2) supported provider property 3) supported and non + * supported provider property + */ + @Test + public void jsonWriterFactoryTest4() throws Fault { + boolean pass = true; + JsonWriterFactory writerFactory; + Map<String, ?> config; + try { + System.out.println("----------------------------------------------"); + System.out.println("Test scenario1: no supported provider property"); + System.out.println("----------------------------------------------"); + System.out.println("Create JsonWriterFactory with Map<String, ?> with EMPTY config"); + writerFactory = Json.createWriterFactory(JSONP_Util.getEmptyConfig()); + config = writerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("-------------------------------------------"); + System.out.println("Test scenario2: supported provider property"); + System.out.println("-------------------------------------------"); + System.out.println("Create JsonWriterFactory with Map<String, ?> with FOO config"); + writerFactory = Json.createWriterFactory(JSONP_Util.getFooConfig()); + config = writerFactory.getConfigInUse(); + String[] props = { JsonGenerator.PRETTY_PRINTING, }; + if (!JSONP_Util.doConfigCheck(config, 0)) + pass = false; + + System.out.println("-------------------------------------------------------------"); + System.out.println("Test scenario3: supported and non supported provider property"); + System.out.println("-------------------------------------------------------------"); + System.out.println("Create JsonGeneratorFactory with Map<String, ?> with all config"); + writerFactory = Json.createWriterFactory(JSONP_Util.getAllConfig()); + config = writerFactory.getConfigInUse(); + if (!JSONP_Util.doConfigCheck(config, 1, props)) + pass = false; + } catch (Exception e) { + throw new Fault("jsonWriterFactoryTest4 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterFactoryTest4 Failed"); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonwritertests/ClientTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonwritertests/ClientTests.java new file mode 100644 index 0000000..19bed5b --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonwritertests/ClientTests.java
@@ -0,0 +1,1108 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonwritertests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.common.*; +import jakarta.jsonp.tck.lib.harness.Fault; + +import java.io.*; +import java.util.*; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.json.*; + +// $Id$ +@RunWith(Arquillian.class) +public class ClientTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, ClientTests.class.getPackage().getName()); + } + /* Tests */ + + /* + * @testName: jsonWriterTest1 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:106; JSONP:JAVADOC:110; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonObject. + * Comparison is done by reading the JsonWriter output using JsonReader and + * recreating the JsonObject and than performing a JsonObject comparison for + * equality. + * + * Tests using API methods: Json.createWriter(Writer) and + * writer.writeObject(JsonObject) + * + */ + @Test + public void jsonWriterTest1() throws Fault { + boolean pass = true; + try { + + System.out.println("Create sample JsonObject for testing"); + JsonObject myJsonObject1 = JSONP_Util.createSampleJsonObject(); + + System.out.println("Write the JsonObject 'myJsonObject1' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeObject(myJsonObject1); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String contents = sWriter.toString(); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + contents); + + System.out.println( + "Read the JsonObject back into 'myJsonObject2' using a JsonReader"); + JsonReader reader = Json.createReader(new StringReader(contents)); + JsonObject myJsonObject2 = (JsonObject) reader.read(); + + System.out.println("Compare myJsonObject1 and myJsonObject2 for equality"); + pass = JSONP_Util.assertEqualsJsonObjects(myJsonObject1, myJsonObject2); + } catch (Exception e) { + throw new Fault("jsonWriterTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterTest1 Failed"); + } + + /* + * @testName: jsonWriterTest2 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:187; JSONP:JAVADOC:110; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonObject. + * Comparison is done by comparing the expected JsonObject text output with + * the actual JsonObject text output from the JsonWriter for equality. + * + * Tests using API methods: Json.createWriter(OutputStream) and + * writer.writeObject(JsonObject) + * + */ + @Test + public void jsonWriterTest2() throws Fault { + boolean pass = true; + try { + + System.out.println("Create sample JsonObject for testing"); + JsonObject myJsonObject1 = JSONP_Util.createSampleJsonObject(); + + System.out.println("Write the JsonObject 'myJsonObject1' out to a JsonWriter"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriter(baos); + writer.writeObject(myJsonObject1); + System.out.println("Close JsonWriter"); + baos.close(); + writer.close(); + + System.out.println("Save contents of the JsonWriter as a String"); + String actJsonObjectText = baos.toString("UTF-8"); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + actJsonObjectText); + + System.out.println( + "Compare expected JsonObject text with actual JsonObject text for equality"); + pass = JSONP_Util.assertEqualsJsonText( + JSONP_Util.EXPECTED_SAMPLEJSONOBJECT_TEXT, actJsonObjectText); + } catch (Exception e) { + throw new Fault("jsonWriterTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterTest2 Failed"); + } + + /* + * @testName: jsonWriterTest3 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:106; JSONP:JAVADOC:107; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonArray. + * Comparison is done by reading the JsonWriter output using JsonReader and + * recreating the JsonArray and than performing a JsonArray comparison for + * equality. + * + * Tests using API methods: Json.createWriter(Writer) and + * writer.writeArray(JsonArray) + * + */ + @Test + public void jsonWriterTest3() throws Fault { + boolean pass = true; + try { + + System.out.println("Create sample JsonArray for testing"); + JsonArray myJsonArray1 = JSONP_Util.createSampleJsonArray(); + + System.out.println("Write the JsonArray 'myJsonArray1' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.writeArray(myJsonArray1); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String contents = sWriter.toString(); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + contents); + + System.out.println("Read the JsonArray back into 'myJsonArray2' using a JsonReader"); + JsonArray myJsonArray2; + try (JsonReader reader = Json.createReader(new StringReader(contents))) { + myJsonArray2 = (JsonArray) reader.read(); + System.out.println("Close JsonReader"); + } + + System.out.println("Compare myJsonArray1 and myJsonArray2 for equality"); + pass = JSONP_Util.assertEqualsJsonArrays(myJsonArray1, myJsonArray2); + } catch (Exception e) { + throw new Fault("jsonWriterTest3 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterTest3 Failed"); + } + + /* + * @testName: jsonWriterTest4 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:187; JSONP:JAVADOC:107; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonArray. + * Comparison is done by comparing the expected JsonArray text output with the + * actual JsonArray text output from the JsonWriter for equality. + * + * Tests using API methods: Json.createWriter(OutputStream) and + * writer.writeArray(JsonArray) + * + */ + @Test + public void jsonWriterTest4() throws Fault { + boolean pass = true; + try { + + System.out.println("Create sample JsonArray for testing"); + JsonArray myJsonArray1 = JSONP_Util.createSampleJsonArray(); + + System.out.println("Write the JsonArray 'myJsonArray1' out to a JsonWriter"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriter(baos); + writer.writeArray(myJsonArray1); + System.out.println("Close JsonWriter"); + baos.close(); + writer.close(); + + System.out.println("Save contents of the JsonWriter as a String"); + String actJsonArrayText = baos.toString("UTF-8"); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + actJsonArrayText); + + System.out.println( + "Compare expected JsonArray text with actual JsonArray text for equality"); + pass = JSONP_Util.assertEqualsJsonText( + JSONP_Util.EXPECTED_SAMPLEJSONARRAY_TEXT, actJsonArrayText); + } catch (Exception e) { + throw new Fault("jsonWriterTest4 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterTest4 Failed"); + } + + /* + * @testName: jsonWriterTest5 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:424; JSONP:JAVADOC:110; + * JSONP:JAVADOC:452; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonObject. + * Comparison is done by comparing the expected JsonObject text output with + * the actual JsonObject text output from the JsonWriter for equality. + * + * Tests using API methods: + * Json.createWriterFactory(Map<String,?>).createWriter(OutputStream, Charset) + * writer.writeObject(JsonObject) + * + * For encoding use UTF-16BE. + */ + @Test + public void jsonWriterTest5() throws Fault { + boolean pass = true; + try { + + System.out.println("Create sample JsonObject for testing"); + JsonObject myJsonObject1 = JSONP_Util.createSampleJsonObject(); + + System.out.println("Write the JsonObject 'myJsonObject1' out to a JsonWriter"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriterFactory(JSONP_Util.getEmptyConfig()) + .createWriter(baos, JSONP_Util.UTF_16BE); + writer.writeObject(myJsonObject1); + System.out.println("Close JsonWriter"); + baos.close(); + writer.close(); + + System.out.println("Save contents of the JsonWriter as a String"); + String actJsonObjectText = JSONP_Util + .removeWhitespace(baos.toString("UTF-16BE")); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + actJsonObjectText); + + System.out.println( + "Compare expected JsonObject text with actual JsonObject text for equality"); + pass = JSONP_Util.assertEqualsJsonText( + JSONP_Util.EXPECTED_SAMPLEJSONOBJECT_TEXT, actJsonObjectText); + } catch (Exception e) { + throw new Fault("jsonWriterTest5 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterTest5 Failed"); + } + + /* + * @testName: jsonWriterTest6 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:424; JSONP:JAVADOC:107; + * JSONP:JAVADOC:452; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonArray. + * Comparison is done by comparing the expected JsonArray text output with the + * actual JsonArray text output from the JsonWriter for equality. + * + * Tests using API methods: + * Json.createWriterFactory.createWriter(OutputStream, Charset) + * writer.writeArray(JsonArray) + * + * For encoding use UTF-8. + */ + @Test + public void jsonWriterTest6() throws Fault { + boolean pass = true; + try { + + System.out.println("Create a configuration with PRETT_PRINTING enabled."); + Map<String, ?> config = JSONP_Util.getPrettyPrintingConfig(); + + System.out.println("Create sample JsonArray for testing"); + JsonArray myJsonArray1 = JSONP_Util.createSampleJsonArray(); + + System.out.println("Write the JsonArray 'myJsonArray1' out to a JsonWriter"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriterFactory(config).createWriter(baos, + JSONP_Util.UTF_8); + writer.writeArray(myJsonArray1); + System.out.println("Close JsonWriter"); + baos.close(); + writer.close(); + + System.out.println("Save contents of the JsonWriter as a String"); + String actJsonArrayText = JSONP_Util + .removeWhitespace(baos.toString("UTF-8")); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + actJsonArrayText); + + System.out.println( + "Compare expected JsonArray text with actual JsonArray text for equality"); + pass = JSONP_Util.assertEqualsJsonText( + JSONP_Util.EXPECTED_SAMPLEJSONARRAY_TEXT, actJsonArrayText); + } catch (Exception e) { + throw new Fault("jsonWriterTest6 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterTest6 Failed"); + } + + /* + * @testName: jsonWriterTest7 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:106; JSONP:JAVADOC:191; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonObject. + * Comparison is done by reading the JsonWriter output using JsonReader and + * recreating the JsonObject and than performing a JsonObject comparison for + * equality. + * + * Tests using API methods: Json.createWriter(Writer) and + * writer.write(JsonStructure) + * + */ + @Test + public void jsonWriterTest7() throws Fault { + boolean pass = true; + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject myJsonObject1 = JSONP_Util.createSampleJsonObject(); + + System.out.println("Write the JsonObject 'myJsonObject1' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.write(myJsonObject1); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String contents = sWriter.toString(); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + contents); + + System.out.println( + "Read the JsonObject back into 'myJsonObject2' using a JsonReader"); + JsonReader reader = Json.createReader(new StringReader(contents)); + JsonObject myJsonObject2 = (JsonObject) reader.read(); + + System.out.println("Compare myJsonObject1 and myJsonObject2 for equality"); + pass = JSONP_Util.assertEqualsJsonObjects(myJsonObject1, myJsonObject2); + } catch (Exception e) { + throw new Fault("jsonWriterTest7 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterTest7 Failed"); + } + + /* + * @testName: jsonWriterTest8 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:106; JSONP:JAVADOC:191; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonArray. + * Comparison is done by reading the JsonWriter output using JsonReader and + * recreating the JsonArray and than performing a JsonArray comparison for + * equality. + * + * Tests using API methods: Json.createWriter(Writer) and + * writer.write(JsonStructure) + * + */ + @Test + public void jsonWriterTest8() throws Fault { + boolean pass = true; + try { + + System.out.println("Create sample JsonArray for testing"); + JsonArray myJsonArray1 = JSONP_Util.createSampleJsonArray(); + + System.out.println("Write the JsonArray 'myJsonArray1' out to a JsonWriter"); + StringWriter sWriter = new StringWriter(); + try (JsonWriter writer = Json.createWriter(sWriter)) { + writer.write(myJsonArray1); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String contents = sWriter.toString(); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + contents); + + System.out.println("Read the JsonArray back into 'myJsonArray2' using a JsonReader"); + JsonReader reader = Json.createReader(new StringReader(contents)); + JsonArray myJsonArray2 = (JsonArray) reader.read(); + + System.out.println("Compare myJsonArray1 and myJsonArray2 for equality"); + pass = JSONP_Util.assertEqualsJsonArrays(myJsonArray1, myJsonArray2); + } catch (Exception e) { + throw new Fault("jsonWriterTest8 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterTest8 Failed"); + } + + /* + * @testName: jsonWriterUTFEncodedTests + * + * @assertion_ids: JSONP:JAVADOC:110; JSONP:JAVADOC:423; JSONP:JAVADOC:452; + * + * @test_Strategy: Tests various JsonWriter API's to create a JsonObject. + * + * The output is written to an OutputStream using all supported UTF encodings + * and read back as a string and filtered to remove whitespace and is compared + * against an expected string. The following UTF encodings are tested: + * + * UTF8 UTF16 UTF16LE UTF16BE UTF32LE UTF32BE + * + * { "object":{"string":"string","number":1,"true":true,"false":false,"null": + * null}, "array":["string", 1, true, false, null] } + */ + @Test + public void jsonWriterUTFEncodedTests() throws Fault { + boolean pass = true; + System.out.println( + "Create expected JSON text with no whitespace for use in comparsion"); + String expJson = "{\"object\":{\"string\":\"string\",\"number\":1,\"true\":true,\"false\":false,\"null\":null},\"array\":[\"string\",1,true,false,null]}"; + try { + System.out.println( + "-----------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createWriterFactory(Map<String,?>).createWriter(OutputStream, Charset) as UTF-8]"); + System.out.println( + "-----------------------------------------------------------------------------------------------"); + System.out.println("Create JsonWriter using UTF-8 encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriterFactory(JSONP_Util.getEmptyConfig()) + .createWriter(baos, JSONP_Util.UTF_8); + JSONP_Util.writeJsonObjectFromString(writer, expJson); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-8")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-8 encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-8")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing generation to UTF-8 encoding: " + e); + } + try { + System.out.println( + "------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createWriterFactory(Map<String,?>).createWriter(OutputStream, Charset) as UTF-16]"); + System.out.println( + "------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonWriter using UTF-16 encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriterFactory(JSONP_Util.getEmptyConfig()) + .createWriter(baos, JSONP_Util.UTF_16); + JSONP_Util.writeJsonObjectFromString(writer, expJson); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-16")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-16 encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-16")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println("Exception occurred testing generation to UTF-16 encoding: " + e); + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createWriterFactory(Map<String,?>).createWriter(OutputStream, Charset) as UTF-16LE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonWriter using UTF-16LE encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriterFactory(JSONP_Util.getEmptyConfig()) + .createWriter(baos, JSONP_Util.UTF_16LE); + JSONP_Util.writeJsonObjectFromString(writer, expJson); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-16LE")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-16LE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-16LE")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println( + "Exception occurred testing generation to UTF-16LE encoding: " + e); + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createWriterFactory(Map<String,?>).createWriter(OutputStream, Charset) as UTF-16BE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonWriter using UTF-16BE encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriterFactory(JSONP_Util.getEmptyConfig()) + .createWriter(baos, JSONP_Util.UTF_16BE); + JSONP_Util.writeJsonObjectFromString(writer, expJson); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-16BE")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-16BE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-16BE")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println( + "Exception occurred testing generation to UTF-16BE encoding: " + e); + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createWriterFactory(Map<String,?>).createWriter(OutputStream, Charset) as UTF-32LE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonWriter using UTF-32LE encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriterFactory(JSONP_Util.getEmptyConfig()) + .createWriter(baos, JSONP_Util.UTF_32LE); + JSONP_Util.writeJsonObjectFromString(writer, expJson); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-32LE")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-32LE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-32LE")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println( + "Exception occurred testing generation to UTF-32LE encoding: " + e); + } + try { + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println( + "TEST CASE [Json.createWriterFactory(Map<String,?>).createWriter(OutputStream, Charset) as UTF-32BE]"); + System.out.println( + "--------------------------------------------------------------------------------------------------"); + System.out.println("Create JsonWriter using UTF-32BE encoding"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriterFactory(JSONP_Util.getEmptyConfig()) + .createWriter(baos, JSONP_Util.UTF_32BE); + JSONP_Util.writeJsonObjectFromString(writer, expJson); + + // Dump JsonText output + System.out.println("Generated Output=" + baos.toString("UTF-32BE")); + + // Do comparison + System.out.println( + "Read the JSON text back from OutputStream using UTF-32BE encoding removing whitespace"); + String actJson = JSONP_Util.removeWhitespace(baos.toString("UTF-32BE")); + if (!JSONP_Util.assertEqualsJsonText(expJson, actJson)) + pass = false; + + } catch (Exception e) { + pass = false; + System.err.println( + "Exception occurred testing generation to UTF-32BE encoding: " + e); + } + if (!pass) + throw new Fault("jsonWriterUTFEncodedTests Failed"); + } + + /* + * @testName: jsonWriterWithConfigTest1 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:422; JSONP:JAVADOC:110; + * JSONP:JAVADOC:452; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonObject. + * Comparison is done by comparing the expected JsonObject text output with + * the actual JsonObject text output from the JsonWriter for equality. + * + * Tests using API methods: + * Json.createWriterFactory(Map<String,?>).createWriter(Writer) + * writer.writeObject(JsonObject) + * + */ + @Test + public void jsonWriterWithConfigTest1() throws Fault { + boolean pass = true; + try { + + System.out.println("Create a configuration with PRETT_PRINTING enabled."); + Map<String, ?> config = JSONP_Util.getPrettyPrintingConfig(); + + System.out.println("Create sample JsonObject for testing"); + JsonObject myJsonObject1 = JSONP_Util.createSampleJsonObject(); + + System.out.println("Write the JsonObject 'myJsonObject1' out to a JsonWriter"); + StringWriter swriter = new StringWriter(); + try (JsonWriter writer = Json.createWriterFactory(config) + .createWriter(swriter)) { + writer.writeObject(myJsonObject1); + System.out.println("Close JsonWriter"); + } + + System.out.println("Save contents of the JsonWriter as a String"); + String actJsonObjectText = JSONP_Util + .removeWhitespace(swriter.toString()); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + actJsonObjectText); + + System.out.println( + "Compare expected JsonObject text with actual JsonObject text for equality"); + pass = JSONP_Util.assertEqualsJsonText( + JSONP_Util.EXPECTED_SAMPLEJSONOBJECT_TEXT, actJsonObjectText); + } catch (Exception e) { + throw new Fault("jsonWriterWithConfigTest1 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterWithConfigTest1 Failed"); + } + + /* + * @testName: jsonWriterWithConfigTest2 + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:423; JSONP:JAVADOC:107; + * + * @test_Strategy: Tests JsonWriter API's for writing out a JsonArray. + * Comparison is done by comparing the expected JsonArray text output with the + * actual JsonArray text output from the JsonWriter for equality. + * + * Tests using API methods: + * Json.createWriterFactory(Map<String,?>).creatWriter(OutputStream) + * writer.writeArray(JsonArray) + * + */ + @Test + public void jsonWriterWithConfigTest2() throws Fault { + boolean pass = true; + try { + + System.out.println("Create a configuration with PRETT_PRINTING enabled."); + Map<String, ?> config = JSONP_Util.getPrettyPrintingConfig(); + + System.out.println("Create sample JsonArray for testing"); + JsonArray myJsonArray1 = JSONP_Util.createSampleJsonArray(); + + System.out.println("Write the JsonArray 'myJsonArray1' out to a JsonWriter"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonWriter writer = Json.createWriterFactory(config).createWriter(baos); + writer.writeArray(myJsonArray1); + System.out.println("Close JsonWriter"); + baos.close(); + writer.close(); + + System.out.println("Save contents of the JsonWriter as a String"); + String actJsonArrayText = JSONP_Util + .removeWhitespace(baos.toString("UTF-8")); + + System.out.println("Dump contents of JsonWriter as a String"); + System.out.println("JsonWriterContents=" + actJsonArrayText); + + System.out.println( + "Compare expected JsonArray text with actual JsonArray text for equality"); + pass = JSONP_Util.assertEqualsJsonText( + JSONP_Util.EXPECTED_SAMPLEJSONARRAY_TEXT, actJsonArrayText); + } catch (Exception e) { + throw new Fault("jsonWriterWithConfigTest2 Failed: ", e); + } + if (!pass) + throw new Fault("jsonWriterWithConfigTest2 Failed"); + } + + /* + * @testName: jsonWriterExceptionTests + * + * @assertion_ids: JSONP:JAVADOC:105; JSONP:JAVADOC:106; JSONP:JAVADOC:109; + * JSONP:JAVADOC:112; JSONP:JAVADOC:222; + * + * @test_Strategy: Test for JsonWriter exception test conditions. o + * IllegalStateException + * + */ + @Test + public void jsonWriterExceptionTests() throws Fault { + boolean pass = true; + JsonWriter writer = null; + + // IllegalStateException if writer.close() already called before + // writer.writeArray(JsonArray) + try { + System.out.println("Create sample JsonArray for testing"); + JsonArray jsonArray = JSONP_Util.createSampleJsonArray(); + + System.out.println("Create JsonWriter, write something and close it"); + StringWriter sWriter = new StringWriter(); + writer = Json.createWriter(sWriter); + writer.writeArray(jsonArray); + writer.close(); + + System.out.println( + "IllegalStateException if writer.close() already called before writer.writeArray(JsonArray)"); + writer.writeArray(jsonArray); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // IllegalStateException if writer.writeArray() called after + // writer.writeArray(JsonArray) + try { + System.out.println("Create sample JsonArray for testing"); + JsonArray jsonArray = JSONP_Util.createSampleJsonArray(); + + System.out.println("Create JsonWriter and write out array"); + StringWriter sWriter = new StringWriter(); + writer = Json.createWriter(sWriter); + writer.writeArray(jsonArray); + + System.out.println( + "IllegalStateException if writer.writeArray(JsonArray) called after writer.writeArray(JsonArray)"); + writer.writeArray(jsonArray); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (writer != null) + writer.close(); + } + + // IllegalStateException if writer.writeObject() called after + // writer.writeArray(JsonArray) + try { + System.out.println("Create sample JsonArray for testing"); + JsonArray jsonArray = JSONP_Util.createSampleJsonArray(); + + System.out.println("Create sample JsonObject for testing"); + JsonObject jsonObject = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create JsonWriter and write out array"); + StringWriter sWriter = new StringWriter(); + writer = Json.createWriter(sWriter); + writer.writeArray(jsonArray); + + System.out.println( + "IllegalStateException if writer.writeObject(JsonObject) called after writer.writeArray(JsonArray)"); + writer.writeObject(jsonObject); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (writer != null) + writer.close(); + } + + // IllegalStateException if writer.close() already called before + // writer.writeObject(JsonArray) + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject jsonObject = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create JsonWriter, write something and close it"); + StringWriter sWriter = new StringWriter(); + writer = Json.createWriter(sWriter); + writer.writeObject(jsonObject); + writer.close(); + + System.out.println( + "IllegalStateException if writer.close() already called before writer.writeObject(JsonObject)"); + writer.writeObject(jsonObject); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // IllegalStateException if writer.writeObject() called after + // writer.writeObject(JsonObject) + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject jsonObject = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create JsonWriter and write out object"); + StringWriter sWriter = new StringWriter(); + writer = Json.createWriter(sWriter); + writer.writeObject(jsonObject); + + System.out.println( + "IllegalStateException if writer.writeObject(JsonObject) called after writer.writeObject(JsonObject)"); + writer.writeObject(jsonObject); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (writer != null) + writer.close(); + } + + // IllegalStateException if writer.writeArray() called after + // writer.writeObject(JsonObject) + try { + System.out.println("Create sample JsonArray for testing"); + JsonArray jsonArray = JSONP_Util.createSampleJsonArray(); + + System.out.println("Create sample JsonObject for testing"); + JsonObject jsonObject = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create JsonWriter and write out object"); + StringWriter sWriter = new StringWriter(); + writer = Json.createWriter(sWriter); + writer.writeObject(jsonObject); + + System.out.println( + "IllegalStateException if writer.writeArray(JsonArray) called after writer.writeObject(JsonObject)"); + writer.writeArray(jsonArray); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (writer != null) + writer.close(); + } + + // IllegalStateException if writer.close() already called before + // writer.write(JsonArray) + try { + System.out.println("Create sample JsonArray for testing"); + JsonArray jsonArray = JSONP_Util.createSampleJsonArray(); + + System.out.println("Create JsonWriter, write something and close it"); + StringWriter sWriter = new StringWriter(); + writer = Json.createWriter(sWriter); + writer.write(jsonArray); + writer.close(); + + System.out.println( + "IllegalStateException if writer.close() already called before writer.write(JsonArray)"); + writer.write(jsonArray); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // IllegalStateException if writer.write(JsonArray) called after + // writer.writeArray(JsonArray) + try { + System.out.println("Create sample JsonArray for testing"); + JsonArray jsonArray = JSONP_Util.createSampleJsonArray(); + + System.out.println("Create JsonWriter and write out array"); + StringWriter sWriter = new StringWriter(); + writer = Json.createWriter(sWriter); + writer.writeArray(jsonArray); + + System.out.println( + "IllegalStateException if writer.write(JsonArray) called after writer.writeArray(JsonArray)"); + writer.write(jsonArray); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (writer != null) + writer.close(); + } + + // IllegalStateException if writer.write(JsonObject) called after + // writer.writeJsonObject(JsonObject) + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject jsonObject = JSONP_Util.createSampleJsonObject(); + + System.out.println("Create JsonWriter and write out object"); + StringWriter sWriter = new StringWriter(); + writer = Json.createWriter(sWriter); + writer.writeObject(jsonObject); + + System.out.println( + "IllegalStateException if writer.write(JsonObject) called after writer.writeObject(JsonObject)"); + writer.write(jsonObject); + pass = false; + System.err.println("Failed to throw IllegalStateException"); + } catch (IllegalStateException e) { + System.out.println("Got expected IllegalStateException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } finally { + if (writer != null) + writer.close(); + } + + if (!pass) + throw new Fault("jsonWriterExceptionTests Failed"); + } + + /* + * @testName: jsonWriterIOErrorTests + * + * @assertion_ids: JSONP:JAVADOC:108; JSONP:JAVADOC:111; JSONP:JAVADOC:221; + * JSONP:JAVADOC:414; + * + * @test_Strategy: Tests for JsonException for testable i/o errors. + * + */ + @Test + public void jsonWriterIOErrorTests() throws Fault { + boolean pass = true; + + // Trip JsonException if there is an i/o error on JsonWriter.close() + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject myJsonObject = JSONP_Util.createSampleJsonObject(); + System.out.println( + "Trip JsonException if there is an i/o error on JsonWriter.close()."); + MyBufferedWriter mbw = new MyBufferedWriter(new StringWriter()); + try (JsonWriter writer = Json.createWriter(mbw)) { + writer.writeObject(myJsonObject); + mbw.setThrowIOException(true); + System.out.println("Calling JsonWriter.close()"); + } + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonException if there is an i/o error on + // JsonWriter.writeObject(JsonObject) + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject myJsonObject = JSONP_Util.createSampleJsonObject(); + System.out.println( + "Trip JsonException if there is an i/o error on JsonWriter.writeObject(JsonObject)."); + MyBufferedWriter mbw = new MyBufferedWriter(new StringWriter()); + try (JsonWriter writer = Json.createWriter(mbw)) { + mbw.setThrowIOException(true); + System.out.println("Calling JsonWriter.writeObject(JsonObject)"); + writer.writeObject(myJsonObject); + } + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonException if there is an i/o error on + // JsonWriter.writeArray(JsonArray) + try { + System.out.println("Create sample JsonArray for testing"); + JsonArray myJsonArray = JSONP_Util.createSampleJsonArray(); + System.out.println( + "Trip JsonException if there is an i/o error on JsonWriter.writeArray(JsonArray)."); + MyBufferedWriter mbw = new MyBufferedWriter(new StringWriter()); + try (JsonWriter writer = Json.createWriter(mbw)) { + mbw.setThrowIOException(true); + System.out.println("Calling JsonWriter.writeArray(JsonArray)"); + writer.writeArray(myJsonArray); + } + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + // Trip JsonException if there is an i/o error on + // JsonWriter.write(JsonStructure) + try { + System.out.println("Create sample JsonObject for testing"); + JsonObject myJsonObject = JSONP_Util.createSampleJsonObject(); + System.out.println( + "Trip JsonException if there is an i/o error on JsonWriter.write(JsonStructure)."); + MyBufferedWriter mbw = new MyBufferedWriter(new StringWriter()); + try (JsonWriter writer = Json.createWriter(mbw)) { + mbw.setThrowIOException(true); + System.out.println("Calling JsonWriter.write(JsonStructure)"); + writer.write(myJsonObject); + } + System.err.println("Did not get expected JsonException"); + pass = false; + } catch (JsonException e) { + System.out.println("Caught expected JsonException"); + } catch (Exception e) { + pass = false; + System.err.println("Caught unexpected exception: " + e); + } + + if (!pass) + throw new Fault("jsonWriterIOErrorTests Failed"); + } + + /* + * @testName: jsonWriter11Test + * + * @assertion_ids: JSONP:JAVADOC:650; JSONP:JAVADOC:583; JSONP:JAVADOC:584; + * JSONP:JAVADOC:585; JSONP:JAVADOC:586; JSONP:JAVADOC:587; JSONP:JAVADOC:588; + * JSONP:JAVADOC:662; JSONP:JAVADOC:663; JSONP:JAVADOC:664; JSONP:JAVADOC:665; + * JSONP:JAVADOC:666; JSONP:JAVADOC:667; + * + * @test_Strategy: Tests JsonWriter API methods added in JSON-P 1.1. + */ + @Test + public void jsonWriter11Test() throws Fault { + Writer writerTest = new Writer(); + final TestResult result = writerTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonwritertests/Writer.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonwritertests/Writer.java new file mode 100644 index 0000000..8de8832 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/jsonwritertests/Writer.java
@@ -0,0 +1,209 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.jsonwritertests; + +import jakarta.jsonp.tck.api.common.JsonValueType; +import jakarta.jsonp.tck.api.common.SimpleValues; +import jakarta.jsonp.tck.api.common.TestResult; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import jakarta.json.Json; +import jakarta.json.JsonException; +import jakarta.json.JsonValue; +import jakarta.json.JsonWriter; +import jakarta.json.stream.JsonParser; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests for {@link JsonWriter}. + */ +public class Writer { + + /** Tests input data. */ + private static final Object[] VALUES = new Object[] { OBJ_VALUE, // write(JsonValue) + // for + // JsonObject + createEmptyArrayWithStr(), // write(JsonValue) for simple JsonArray + STR_VALUE, // write(JsonValue) for String + INT_VALUE, // write(JsonValue) for int + LNG_VALUE, // write(JsonValue) for long + DBL_VALUE, // write(JsonValue) for double + BIN_VALUE, // write(JsonValue) for BigInteger + BDC_VALUE, // write(JsonValue) for BigDecimal + BOOL_VALUE, // write(JsonValue) for boolean + null // write(JsonValue) for null + }; + + /** + * Creates an instance of JavaScript Object Notation (JSON) compatibility + * tests for {@link JsonWriter}. + */ + Writer() { + super(); + } + + /** + * {@link JsonWriter} API methods added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonWriter API methods added in JSON-P 1.1."); + System.out.println("JsonWriter API methods added in JSON-P 1.1."); + testWriteValue(result); + testDoubleWriteValue(result); + testIOExceptionOnWriteValue(result); + return result; + } + + /** + * Test {@code void write(JsonValue)} method on all child types of + * {@code JsonValue}. + * + * @param result + * Test suite result. + */ + private void testWriteValue(final TestResult result) { + for (Object value : VALUES) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println(" - write(JsonValue) for " + typeName + " as an argument"); + final JsonValue jsonValue = SimpleValues.toJsonValue(value); + final StringWriter strWriter = new StringWriter(); + try (final JsonWriter writer = Json.createWriter(strWriter)) { + writer.write(jsonValue); + } catch (JsonException ex) { + System.out.println("Caught JsonException: " + ex.getLocalizedMessage()); + result.fail("write(JsonValue)", + "Caught JsonException: " + ex.getLocalizedMessage()); + } + final String data = strWriter.toString(); + System.out.println(" - Data: " + data); + final JsonParser parser = Json.createParser(new StringReader(data)); + parser.next(); + final JsonValue outValue = parser.getValue(); + if (operationFailed(jsonValue, outValue)) { + result.fail("write(JsonValue)", + "Writer output " + valueToString(outValue) + " value shall be " + + valueToString(jsonValue)); + } + } + } + + /** + * Test {@code void write(JsonValue)} method with duplicated {@code JsonValue} + * write call. Second call is expected to throw {@code IllegalStateException} + * exception. + * + * @param result + * Test suite result. + */ + private void testDoubleWriteValue(final TestResult result) { + for (Object value : VALUES) { + final String typeName = JsonValueType.getType(value).name(); + System.out.println( + " - duplicate write(JsonValue) for " + typeName + " as an argument"); + final JsonValue jsonValue = SimpleValues.toJsonValue(value); + final StringWriter strWriter = new StringWriter(); + try (final JsonWriter writer = Json.createWriter(strWriter)) { + // 1st attempt to write the data shall pass + writer.write(jsonValue); + try { + // 2nd attempt to write the data shall throw IllegalStateException + writer.write(jsonValue); + result.fail("write(JsonValue)", + "Duplicate call of write(JsonValue) shall throw IllegalStateException"); + } catch (IllegalStateException ex) { + System.out.println(" - Expected exception: " + ex.getMessage()); + } catch (Throwable t) { + result.fail("write(JsonValue)", + "Duplicate call of write(JsonValue) shall throw IllegalStateException, not " + + t.getClass().getSimpleName()); + } + } catch (JsonException ex) { + System.out.println("Caught JsonException: " + ex.getLocalizedMessage()); + result.fail("write(JsonValue)", + "Caught JsonException: " + ex.getLocalizedMessage()); + } + } + } + + /** + * Test {@code void write(JsonValue)} method with write call that causes + * IOException. IOException shall be encapsulated in JsonException. + * + * @param result + * Test suite result. + */ + @SuppressWarnings("ConvertToTryWithResources") + private void testIOExceptionOnWriteValue(final TestResult result) { + System.out.println(" - write(JsonValue) into already closed file writer"); + final JsonValue jsonValue = SimpleValues.toJsonValue(DEF_VALUE); + File temp = null; + JsonWriter writer; + // Close writer before calling write method. + try { + temp = File.createTempFile("testIOExceptionOnWriteValue", ".txt"); + System.out.println(" - Temporary file: " + temp.getAbsolutePath()); + final FileWriter fileWriter = new FileWriter(temp); + writer = Json.createWriter(fileWriter); + fileWriter.close(); + } catch (IOException ex) { + System.out.println("Caught IOException: " + ex.getLocalizedMessage()); + result.fail("write(JsonValue)", + "Caught IOException: " + ex.getLocalizedMessage()); + return; + } finally { + if (temp != null) { + temp.delete(); + } + } + try { + writer.write(jsonValue); + result.fail("write(JsonValue)", + "Call of write(JsonValue) on already closed file writer shall throw JsonException"); + } catch (JsonException ex) { + System.out.println(" - Expected exception: " + ex.getMessage()); + } catch (Throwable t) { + result.fail("write(JsonValue)", + "Call of write(JsonValue) on already closed file writer shall throw JsonException, not " + + t.getClass().getSimpleName()); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeAddValue.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeAddValue.java new file mode 100644 index 0000000..13d5b78 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeAddValue.java
@@ -0,0 +1,183 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.mergetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.JsonObject; + +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * RFC 7396: JavaScript Object Notation (JSON) Merge Patch compatibility + * tests.<br> + * Checks scenario described in + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-1">RFC 7396: 1. + * Introduction</a>}: If the provided merge patch contains members that do not + * appear within the target, those members are added. + */ +public class MergeAddValue extends MergeCommon { + + /** + * Creates an instance of RFC 7396 value adding test. + */ + MergeAddValue() { + super(); + } + + /** + * Test RFC 7396: Adding non existing values. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "RFC 7396: Add non existing values"); + System.out.println("Testing RFC 7396: Add non existing values"); + testStringOnEmptyObject(result); + testStringOnsimpleObject(result); + testIntOnEmptyObject(result); + testIntOnsimpleObject(result); + testBoolOnEmptyObject(result); + testBoolOnsimpleObject(result); + testObjectOnEmptyObject(result); + testObjectOnsimpleObject(result); + return result; + } + + /** + * Test RFC 7396 patch and diff for {@code String} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testStringOnEmptyObject(final TestResult result) { + System.out.println(" - for String on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject patch = createSimpleObjectStr(); + final JsonObject check = createSimpleObjectStr(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testStringOnsimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject patch = createSimpleObjectStr(); + final JsonObject check = createSimpleObjectWithStr(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code int} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testIntOnEmptyObject(final TestResult result) { + System.out.println(" - for int on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject patch = createSimpleObjectInt(); + final JsonObject check = createSimpleObjectInt(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testIntOnsimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject patch = createSimpleObjectInt(); + final JsonObject check = createSimpleObjectWithInt(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code boolean} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testBoolOnEmptyObject(final TestResult result) { + System.out.println(" - for boolean on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject patch = createSimpleObjectBool(); + final JsonObject check = createSimpleObjectBool(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testBoolOnsimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject patch = createSimpleObjectBool(); + final JsonObject check = createSimpleObjectWithBool(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code JsonObject} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testObjectOnEmptyObject(final TestResult result) { + System.out.println(" - for JsonObject on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject patch = createSimpleObjectObject(); + final JsonObject check = createSimpleObjectObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code JsonObject} on compound JSON + * object. + * + * @param result + * Tests result record. + */ + private void testObjectOnsimpleObject(final TestResult result) { + System.out.println(" - for JsonObject on compound JSON object"); + final JsonObject in = createCompoundObject(); + final JsonObject patch = createSimpleObjectObject(); + final JsonObject check = createCompoundObjectWithObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeCommon.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeCommon.java new file mode 100644 index 0000000..1fc3f03 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeCommon.java
@@ -0,0 +1,203 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.mergetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests.<br> + */ +public abstract class MergeCommon { + + /** Message content: "MERGE" operation. */ + private static final String MERGE_STR = "MERGE"; + + /** Message content: "DIFF" operation. */ + private static final String DIFF_STR = "DIFF"; + + /** Message content template for test failure log message: patch. */ + private static final String TEST_FAIL_PATCH = "Patch "; + + /** Message content template for test failure log message: failed on. */ + private static final String TEST_FAIL_ON = " failed on "; + + /** Message content template for test failure log message: value. */ + private static final String TEST_FAIL_VAL = " value"; + + /** Message content template for test failure log message: patch. */ + private static final String TEST_FAIL_FROM = "Diff from "; + + /** Message content template for test failure log message: failed on. */ + private static final String TEST_FAIL_TO = " to "; + + /** Message content template for test failure log message: value. */ + private static final String TEST_FAIL_FAIL = " failed"; + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @param message + * Assert message. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, final JsonValue out, + final String message) { + return out == null || !assertEquals(check, out, message); + } + + /** + * Test helper: Verify merge of JSON patch on provided JSON value and verify + * result using provided expected JSON value. + * + * @param result + * Test suite result. + * @param in + * Source JSON value to be modified. + * @param patch + * JSON patch to be done on source value. + * @param check + * Expected modified JSON object (used for operation check). + */ + protected void simpleMerge(final TestResult result, final JsonValue in, + final JsonValue patch, final JsonValue check) { + final JsonValue out = Json.createMergePatch(patch).apply(in); + if (operationFailed(check, out, MERGE_STR + " mismatch")) { + final String targetClassName = in.getValueType().name().toLowerCase(); + result.fail(testName(MERGE_STR, targetClassName), + testMergeMessage(valueToString(in), valueToString(patch))); + } + } + + /** + * Test helper: Verify diff on provided JSON values and verify result using + * provided expected JSON value. + * + * @param result + * Test suite result. + * @param src + * Source JSON value for diff. + * @param target + * Target JSON value for diff. + * @param diff + * Expected diff JSON object (used for operation check). + */ + protected void simpleDiff(final TestResult result, final JsonValue src, + final JsonValue target, final JsonValue diff) { + final JsonValue out = Json.createMergeDiff(src, target).toJsonValue(); + if (operationFailed(diff, out, DIFF_STR + " mismatch")) { + final String srcClassName = src.getValueType().name().toLowerCase(); + final String targetClassName = target.getValueType().name().toLowerCase(); + result.fail(testName(DIFF_STR, srcClassName, targetClassName), + testDiffMessage(valueToString(src), valueToString(target))); + } + } + + /** + * Build test name for test failure log message. + * + * @param operation + * Name of operation. + * @param targetType + * Name of the target (JSON value being modified) value type. + * @return Test name for test failure log message. + */ + protected String testName(final String operation, final String targetType) { + final StringBuilder sb = new StringBuilder( + operation.length() + targetType.length() + 1); + sb.append(operation); + sb.append(' '); + sb.append(targetType); + return sb.toString(); + } + + /** + * Build test name for test failure log message. + * + * @param operation + * Name of operation. + * @param srcType + * Name of the source (JSON value being used for modification) value + * type. + * @param targetType + * Name of the target (JSON value being modified) value type. + * @return Test name for test failure log message. + */ + protected String testName(final String operation, final String srcType, + final String targetType) { + final StringBuilder sb = new StringBuilder( + operation.length() + srcType.length() + targetType.length() + 2); + sb.append(operation); + sb.append(' '); + sb.append(srcType); + sb.append(','); + sb.append(targetType); + return sb.toString(); + } + + /** + * Build message content for test failure log message. + * + * @param in + * Source JSON value to be modified. + * @param patch + * JSON patch to be done on source value. + * @return Log message content. + */ + protected String testMergeMessage(final String in, final String patch) { + final StringBuilder sb = new StringBuilder( + TEST_FAIL_PATCH.length() + TEST_FAIL_ON.length() + + TEST_FAIL_VAL.length() + patch.length() + in.length()); + sb.append(TEST_FAIL_PATCH); + sb.append(patch); + sb.append(TEST_FAIL_ON); + sb.append(in); + sb.append(TEST_FAIL_VAL); + return sb.toString(); + } + + /** + * Build message content for test failure log message. + * + * @param src + * Source JSON value for diff. + * @param target + * Target JSON value for diff. + * @return Log message content. + */ + protected String testDiffMessage(final String src, final String target) { + final StringBuilder sb = new StringBuilder( + TEST_FAIL_FROM.length() + TEST_FAIL_TO.length() + + TEST_FAIL_FAIL.length() + src.length() + target.length()); + sb.append(TEST_FAIL_FROM); + sb.append(src); + sb.append(TEST_FAIL_TO); + sb.append(target); + sb.append(TEST_FAIL_FAIL); + return sb.toString(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeNonObject.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeNonObject.java new file mode 100644 index 0000000..dbcba22 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeNonObject.java
@@ -0,0 +1,247 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.mergetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * RFC 7396: JavaScript Object Notation (JSON) Merge Patch compatibility + * tests.<br> + * Checks scenario described in + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-1">RFC 7396: 1. + * Introduction</a>}: If the patch is anything other than an object, the result + * will always be to replace the entire target with the entire patch. + */ +public class MergeNonObject extends MergeCommon { + + /** + * Creates an instance of RFC 7396 non object patch test. + */ + MergeNonObject() { + super(); + } + + /** + * Test RFC 7396: Non object patch. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult("RFC 7396: Non object patch"); + System.out.println("Testing RFC 7396: Non object patch"); + testStringOnEmptyObject(result); + testStringOnSimpleObject(result); + testStringOnSimpleArray(result); + testIntOnEmptyObject(result); + testIntOnSimpleObject(result); + testIntOnSimpleArray(result); + testBoolOnEmptyObject(result); + testBoolOnSimpleObject(result); + testBoolOnSimpleArray(result); + testArrayOnEmptyObject(result); + testArrayOnCompoundObject(result); + testArrayOnSimpleArray(result); + return result; + } + + /** + * Test RFC 7396 patch and diff for {@code String} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testStringOnEmptyObject(final TestResult result) { + System.out.println(" - for String on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonValue patch = Json.createValue(STR_VALUE); + final JsonValue check = Json.createValue(STR_VALUE); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code String} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testStringOnSimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObjectWithStr(); + final JsonValue patch = Json.createValue(STR_VALUE); + final JsonValue check = Json.createValue(STR_VALUE); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code String} on empty JSON array. + * + * @param result + * Tests result record. + */ + private void testStringOnSimpleArray(final TestResult result) { + System.out.println(" - for String on simple JSON array"); + final JsonArray in = createStringArray2(); + final JsonValue patch = Json.createValue(STR_VALUE); + final JsonValue check = Json.createValue(STR_VALUE); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code int} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testIntOnEmptyObject(final TestResult result) { + System.out.println(" - for int on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonValue patch = Json.createValue(INT_VALUE); + final JsonValue check = Json.createValue(INT_VALUE); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code int} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testIntOnSimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObjectWithInt(); + final JsonValue patch = Json.createValue(INT_VALUE); + final JsonValue check = Json.createValue(INT_VALUE); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code int} on empty JSON array. + * + * @param result + * Tests result record. + */ + private void testIntOnSimpleArray(final TestResult result) { + System.out.println(" - for int on simple JSON array"); + final JsonArray in = createIntArray2(); + final JsonValue patch = Json.createValue(INT_VALUE); + final JsonValue check = Json.createValue(INT_VALUE); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code boolean} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testBoolOnEmptyObject(final TestResult result) { + System.out.println(" - for boolean on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonValue patch = toJsonValue(BOOL_VALUE); + final JsonValue check = toJsonValue(BOOL_VALUE); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code boolean} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testBoolOnSimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObjectWithBool(); + final JsonValue patch = toJsonValue(BOOL_VALUE); + final JsonValue check = toJsonValue(BOOL_VALUE); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code boolean} on empty JSON array. + * + * @param result + * Tests result record. + */ + private void testBoolOnSimpleArray(final TestResult result) { + System.out.println(" - for boolean on simple JSON array"); + final JsonArray in = createBoolArray2(); + final JsonValue patch = toJsonValue(BOOL_VALUE); + final JsonValue check = toJsonValue(BOOL_VALUE); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code JsonArray} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testArrayOnEmptyObject(final TestResult result) { + System.out.println(" - for JsonArray on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonArray patch = createStringArray1(); + final JsonArray check = createStringArray1(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code JsonArray} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testArrayOnCompoundObject(final TestResult result) { + System.out.println(" - for JsonArray on compound JSON object"); + final JsonObject in = createCompoundObject(); + final JsonValue patch = createStringArray2(); + final JsonValue check = createStringArray2(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code JsonArray} on empty JSON array. + * + * @param result + * Tests result record. + */ + private void testArrayOnSimpleArray(final TestResult result) { + System.out.println(" - for JsonArray on simple JSON array"); + final JsonArray in = createBoolArray2(); + final JsonValue patch = createIntArray2(); + final JsonValue check = createIntArray2(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeRFCSample.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeRFCSample.java new file mode 100644 index 0000000..37dd77f --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeRFCSample.java
@@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.mergetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.JsonObject; + +import static jakarta.jsonp.tck.api.common.MergeRFCObject.*; + +// $Id$ +/** + * RFC 7396: JavaScript Object Notation (JSON) Merge Patch compatibility + * tests.<br> + * Test based on + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-3">RFC 7396: 3. + * Example</a>} objects. + */ +public class MergeRFCSample extends MergeCommon { + + /** + * Creates an instance of RFC 7396 value replacing test. + */ + MergeRFCSample() { + super(); + } + + /** + * Test RFC 7396: Adding non existing values. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult("RFC 7396: Example JSON object"); + System.out.println("Testing RFC 7396: Example JSON object"); + testMerge(result); + testDiff(result); + return result; + } + + /** + * Test RFC 7396 patch for example objects. + * + * @param result + * Tests result record. + */ + private void testMerge(final TestResult result) { + System.out.println(" - merge"); + final JsonObject in = createRFCSourceObject(); + final JsonObject patch = createRFCPatchObject(); + final JsonObject check = createRFCTargetObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 diff for example objects. + * + * @param result + * Tests result record. + */ + private void testDiff(final TestResult result) { + System.out.println(" - diff"); + final JsonObject in = createRFCSourceObject(); + final JsonObject diff = createRFCPatchObject(); + final JsonObject out = createRFCTargetObject(); + simpleDiff(result, in, out, diff); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeRemoveValue.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeRemoveValue.java new file mode 100644 index 0000000..039fb70 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeRemoveValue.java
@@ -0,0 +1,182 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.mergetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.JsonObject; + +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * RFC 7396: JavaScript Object Notation (JSON) Merge Patch compatibility + * tests.<br> + * Checks scenario described in + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-1">RFC 7396: 1. + * Introduction</a>}: {@code null} values in the merge patch are given special + * meaning to indicate the removal of existing values in the target. + */ +public class MergeRemoveValue extends MergeCommon { + + /** + * Creates an instance of RFC 7396 value removal test. + */ + MergeRemoveValue() { + super(); + } + + /** + * Test RFC 7396: Removing existing values. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "RFC 7396: Remove existing values"); + System.out.println("Testing RFC 7396: Remove existing values"); + testStringOnEmptyObject(result); + testStringOnsimpleObject(result); + testIntOnEmptyObject(result); + testIntOnsimpleObject(result); + testBoolOnEmptyObject(result); + testBoolOnsimpleObject(result); + testObjectOnEmptyObject(result); + testObjectOnsimpleObject(result); + return result; + } + + /** + * Test RFC 7396 patch and diff for {@code String} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testStringOnEmptyObject(final TestResult result) { + System.out.println(" - for String to produce empty JSON object"); + final JsonObject in = createSimpleObjectStr(); + final JsonObject patch = createPatchRemoveStr(); + final JsonObject check = createEmptyObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testStringOnsimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObjectWithStr(); + final JsonObject patch = createPatchRemoveStr(); + final JsonObject check = createSimpleObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code int} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testIntOnEmptyObject(final TestResult result) { + System.out.println(" - for int to produce empty JSON object"); + final JsonObject in = createSimpleObjectInt(); + final JsonObject patch = createPatchRemoveInt(); + final JsonObject check = createEmptyObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testIntOnsimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObjectWithInt(); + final JsonObject patch = createPatchRemoveInt(); + final JsonObject check = createSimpleObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code boolean} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testBoolOnEmptyObject(final TestResult result) { + System.out.println(" - for boolean to produce empty JSON object"); + final JsonObject in = createSimpleObjectBool(); + final JsonObject patch = createPatchRemoveBool(); + final JsonObject check = createEmptyObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testBoolOnsimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObjectWithBool(); + final JsonObject patch = createPatchRemoveBool(); + final JsonObject check = createSimpleObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code JsonObject} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testObjectOnEmptyObject(final TestResult result) { + System.out.println(" - for JsonObject to produce empty JSON object"); + final JsonObject in = createSimpleObjectObject(); + final JsonObject patch = createPatchRemoveObject(); + final JsonObject check = createEmptyObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code JsonObject} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testObjectOnsimpleObject(final TestResult result) { + System.out.println(" - for JsonObject on compoubnd JSON object"); + final JsonObject in = createCompoundObjectWithObject(); + final JsonObject patch = createPatchRemoveObject(); + final JsonObject check = createCompoundObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeReplaceValue.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeReplaceValue.java new file mode 100644 index 0000000..5d66b44 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeReplaceValue.java
@@ -0,0 +1,119 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.mergetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.JsonObject; + +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * RFC 7396: JavaScript Object Notation (JSON) Merge Patch compatibility + * tests.<br> + * Checks scenario described in + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-1">RFC 7396: 1. + * Introduction</a>}: If the target does contain the member, the value is + * replaced. + */ +public class MergeReplaceValue extends MergeCommon { + + /** + * Creates an instance of RFC 7396 value replacing test. + */ + MergeReplaceValue() { + super(); + } + + /** + * Test RFC 7396: Adding non existing values. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "RFC 7396: Replace existing values"); + System.out.println("Testing RFC 7396: Replace existing values"); + testStringOnsimpleObject(result); + testIntOnsimpleObject(result); + testBoolOnsimpleObject(result); + testObjectOnsimpleObject(result); + return result; + } + + /** + * Test RFC 7396 patch and diff for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testStringOnsimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject patch = createSimpleObjectMoveStr(); + final JsonObject check = createSimpleObjectMoveStr(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testIntOnsimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject patch = createSimpleObjectMoveInt(); + final JsonObject check = createSimpleObjectMoveInt(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testBoolOnsimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject patch = createSimpleObjectMoveBool(); + final JsonObject check = createSimpleObjectMoveBool(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + + /** + * Test RFC 7396 patch and diff for {@code JsonObject} on compound JSON + * object. + * + * @param result + * Tests result record. + */ + private void testObjectOnsimpleObject(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject patch = createSimpleObjectMoveObject(); + final JsonObject check = createSimpleObjectMoveObject(); + simpleMerge(result, in, patch, check); + simpleDiff(result, in, check, patch); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeTests.java new file mode 100644 index 0000000..b9cd494 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/mergetests/MergeTests.java
@@ -0,0 +1,138 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.mergetests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.lib.harness.Fault; + +import org.junit.Test; + +// $Id$ +/** + * RFC 7396: JavaScript Object Notation (JSON) Merge Patch compatibility + * tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc7396">RFC 7396</a>}. + */ +public class MergeTests { + + /** + * Test JSON-P API response on + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-1">RFC 7396: 1. + * Introduction</a>}: If the provided merge patch contains members that do not + * appear within the target, those members are added. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonMergeAddValueTest + * @assertion_ids: JSONP:JAVADOC:575; JSONP:JAVADOC:576; JSONP:JAVADOC:616; + * JSONP:JAVADOC:617; JSONP:JAVADOC:620; JSONP:JAVADOC:654; + * JSONP:JAVADOC:655; + * @test_Strategy: Test API response on various JSON values. + */ + @Test + public void jsonMergeAddValueTest() throws Fault { + MergeAddValue addTest = new MergeAddValue(); + final TestResult result = addTest.test(); + result.eval(); + } + + /** + * Test JSON-P API response on + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-1">RFC 7396: 1. + * Introduction</a>}: If the target does contain the member, the value is + * replaced. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonMergeReplaceValueTest + * @assertion_ids: JSONP:JAVADOC:575; JSONP:JAVADOC:576; JSONP:JAVADOC:616; + * JSONP:JAVADOC:617; JSONP:JAVADOC:654; JSONP:JAVADOC:655; + * @test_Strategy: Test API response on various JSON values. + */ + @Test + public void jsonMergeReplaceValueTest() throws Fault { + MergeReplaceValue replaceTest = new MergeReplaceValue(); + final TestResult result = replaceTest.test(); + result.eval(); + } + + /** + * Test JSON-P API response on + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-1">RFC 7396: 1. + * Introduction</a>}: {@code null} values in the merge patch are given special + * meaning to indicate the removal of existing values in the target. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonMergeRemoveValueTest + * @assertion_ids: JSONP:JAVADOC:575; JSONP:JAVADOC:576; JSONP:JAVADOC:616; + * JSONP:JAVADOC:617; JSONP:JAVADOC:654; JSONP:JAVADOC:655; + * @test_Strategy: Test API response on various JSON values. + */ + @Test + public void jsonMergeRemoveValueTest() throws Fault { + MergeRemoveValue removeTest = new MergeRemoveValue(); + final TestResult result = removeTest.test(); + result.eval(); + } + + /** + * Test JSON-P API response on + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-1">RFC 7396: 1. + * Introduction</a>}: If the patch is anything other than an object, the + * result will always be to replace the entire target with the entire patch. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonMergeNonObjectTest + * @assertion_ids: JSONP:JAVADOC:575; JSONP:JAVADOC:576; JSONP:JAVADOC:616; + * JSONP:JAVADOC:617; JSONP:JAVADOC:654; JSONP:JAVADOC:655; + * JSONP:JAVADOC:583; JSONP:JAVADOC:584; + * @test_Strategy: Test API response on various JSON values. + */ + @Test + public void jsonMergeNonObjectTest() throws Fault { + MergeNonObject nonObjTest = new MergeNonObject(); + final TestResult result = nonObjTest.test(); + result.eval(); + } + + /** + * Test JSON-P API response on Test based on + * {@see <a href="https://tools.ietf.org/html/rfc7396#section-3">RFC 7396: 3. + * Example</a>} objects. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonMergeRFCSampleTest + * @assertion_ids: JSONP:JAVADOC:575; JSONP:JAVADOC:576; JSONP:JAVADOC:616; + * JSONP:JAVADOC:617; JSONP:JAVADOC:654; JSONP:JAVADOC:655; + * @test_Strategy: Test API response on RFC example objects. + */ + @Test + public void jsonMergeRFCSampleTest() throws Fault { + MergeRFCSample rfcSampleTest = new MergeRFCSample(); + final TestResult result = rfcSampleTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/CommonOperation.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/CommonOperation.java new file mode 100644 index 0000000..0ac6675 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/CommonOperation.java
@@ -0,0 +1,507 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonPatch; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests. + */ +public abstract class CommonOperation { + + /** Message content template for test failure log message: operation name. */ + private static final String TEST_FAIL_OP = " operation"; + + /** Message content template for test failure log message: path. */ + private static final String TEST_FAIL_FOR = " for "; + + /** Message content template for test failure log message: failed. */ + private static final String TEST_FAIL_FAI = " failed"; + + /** + * Message content template for test failure log message: on target type + * prefix. + */ + private static final String TEST_FAIL_ON1 = " on JSON "; + + /** + * Message content template for test failure log message: on target type + * suffix. + */ + private static final String TEST_FAIL_ON2 = " value"; + + /** + * Message content template for test failure log message: patching execution + * method. + */ + private static final String TEST_FAIL_MET = " using "; + + /** + * Creates an instance of JavaScript Object Notation (JSON) compatibility + * tests. + */ + protected CommonOperation() { + super(); + } + + /** + * Tested operation name, e.g. {@code "ADD"}, {@code "REPLACE"}, + * {@code "MOVE"}. Child class callback. + * + * @return Operation name to be used in logs. + */ + protected abstract String operationName(); + + /** + * Create and initialize patch builder to contain patch operation to be + * applied. Child class callback. + * + * @param path + * JSON path of operation. + * @param value + * JSON value used in patch operation. + * @return Patch builder containing operation to be applied. + */ + protected abstract JsonPatchBuilder createOperationBuilder(final String path, + final Object value); + + /** + * Update patch builder to contain next patch operation to be applied. Child + * class callback. + * + * @param builder + * JSON patch builder to update. + * @param path + * JSON path of operation. + * @param value + * JSON value used in patch operation. + * @return Patch builder containing operation to be applied. + */ + protected abstract JsonPatchBuilder updateOperationBuilder( + final JsonPatchBuilder builder, final String path, final Object value); + + /** + * Test helper: Verify simple operation on provided JSON value and verify + * result using provided expected JSON value. Operation execution is done + * using all known methods to build and apply JSON patch. + * + * @param result + * Test suite result. + * @param in + * JSON value to be modified. + * @param check + * Expected modified JSON object (used for operation check). + * @param path + * JSON path of operation. + * @param value + * JSON value used in patch operation. + */ + protected void simpleOperation(final TestResult result, final JsonValue in, + final JsonValue check, final String path, final Object value) { + final JsonPatchBuilder builder = createOperationBuilder(path, value); + final JsonPatch patch = builder.build(); + JsonValue out; + try { + out = patchApply(patch, in); + } catch (JsonException e) { + out = null; + System.out.println( + " Exception for path \"" + path + "\" on " + valueToString(in)); + System.out.println(" " + e.getMessage()); + } + if (operationFailed(check, out)) { + final String targetClassName = in.getValueType().name().toLowerCase(); + final String operation = valueToString(patch.toJsonArray()); + System.out.println(" " + operation); + result.fail(testName(path, targetClassName), + testMessage(operation, path, valueToString(in))); + } + } + + /** + * Test helper: Verify set of operations on provided JSON value and verify + * result using provided expected JSON value. Verification is done using all + * known methods to build and apply JSON patch. This method allows custom + * patching of JSON array. Used for operations without value operand, e.g. + * REMOVE. Operation builder callback will receive {@code null} as value. + * + * @param result + * Test suite result. + * @param in + * JSON array to be modified. + * @param check + * Expected modified JSON array (used for operation check). + * @param paths + * JSON paths array of operations. + */ + protected void complexOperation(final TestResult result, final JsonArray in, + final JsonArray check, final String[] paths) { + final Object[] values = new Object[paths.length]; + for (int i = 0; i < paths.length; i++) { + values[i] = null; + } + complexOperation(result, in, check, paths, values); + } + + /** + * Test helper: Verify set of operations on provided JSON value and verify + * result using provided expected JSON value. Verification is done using all + * known methods to build and apply JSON patch. This method allows custom + * patching of JSON array. + * + * @param result + * Test suite result. + * @param in + * JSON array to be modified. + * @param check + * Expected modified JSON array (used for operation check). + * @param paths + * JSON paths array of operations. Pairs of {@code paths[i]} and + * {@code values[i]} are used for individual operations. + * @param values + * JSON values array used in patch operations. + */ + protected void complexOperation(final TestResult result, final JsonArray in, + final JsonArray check, final String[] paths, final Object[] values) { + if (paths.length != values.length) { + throw new IllegalArgumentException( + "Number of paths does not match number of indexes"); + } + final JsonPatchBuilder builder = prepareComplexBuilder(paths, values); + final JsonPatch patch = builder.build(); + final JsonValue out = patchApply(patch, in); + if (operationFailed(check, out)) { + final String operations = valueToString(patch.toJsonArray()); + final String targetClassName = in.getValueType().name().toLowerCase(); + System.out.println(" " + operations); + result.fail(testName(paths, targetClassName), + testMessage(operations, paths, valueToString(in))); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + + /** + * Builds JSON patch builder with set of operations stored in {@code paths} + * and {@code values}. + * + * @param paths + * JSON paths array of operations. Pairs of {@code paths[i]} and + * {@code values[i]} are used for individual operations. + * @param values + * JSON values array used in patch operations. + */ + private JsonPatchBuilder prepareComplexBuilder(final String[] paths, + final Object[] values) { + JsonPatchBuilder builder = Json.createPatchBuilder(); + for (int i = 0; i < paths.length; i++) { + builder = updateOperationBuilder(builder, paths[i], values[i]); + } + return builder; + } + + /** + * Test helper: Verify that operation on provided JSON value fails. Operation + * execution is done using all known methods to build and apply JSON patch. + * + * @param result + * Test suite result. + * @param in + * JSON value to be modified. + * @param path + * JSON path of operation. + * @param value + * JSON value used in patch operation. + */ + protected void simpleOperationFail(final TestResult result, + final JsonValue in, final String path, final Object value) { + try { + final JsonPatch patch = createOperationBuilder(path, value).build(); + patchApply(patch, in); + final String targetClassName = in.getValueType().name().toLowerCase(); + final String operation = valueToString(patch.toJsonArray()); + System.out.println( + " Failed for path \"" + path + "\" on " + valueToString(in)); + System.out.println(" " + operation); + result.fail(testName(path, targetClassName), + testMessage(operation, path, valueToString(in))); + } catch (JsonException e) { + // There are too many combinations to log them. + // System.out.println(" - Expected exception: "+e.getMessage()); + } + } + + /** + * Get source class name. + * + * @param value + * JSON value to search for class name. + * @return Class name of provided JSON value or {@code null} when this value + * has been {@code null}. + */ + protected String getSrcName(final Object value) { + return value != null ? value.getClass().getSimpleName() : null; + } + + /** + * Get source classes names. + * + * @param values + * JSON values to search for class name. + * @return Class name of provided JSON value or {@code null} when this value + * has been {@code null}. + */ + protected String[] getSrcNames(final Object[] values) { + if (values == null) { + return null; + } + final String[] names = new String[values.length]; + for (int i = 0; i < values.length; i++) { + names[i] = values[i] != null ? values[i].getClass().getSimpleName() + : null; + } + return names; + } + + /** + * Build test name for test failure log message. + * + * @param path + * JSON patch operation source path. + * @param targetType + * Name of target (JSON value being modified) value type. + * @return Test name for test failure log message. + */ + protected String testName(final String path, final String targetType) { + final String operationName = operationName(); + final int pathLen = path != null ? path.length() + 1 : 0; + final StringBuilder sb = new StringBuilder( + operationName.length() + pathLen + targetType.length() + 1); + sb.append(operationName); + if (pathLen > 0) { + sb.append(' '); + sb.append(path); + } + sb.append(' '); + sb.append(targetType); + return sb.toString(); + } + + /** + * Build test name for test failure log message. + * + * @param paths + * JSON patch operation source paths. + * @param targetType + * Name of target (JSON value being modified) value type. + * @return Test name for test failure log message. + */ + protected String testName(final String[] paths, final String targetType) { + final String operationName = operationName(); + final int pathsLen = paths != null ? paths.length : 0; + int pathsSize = 0; + for (int i = 0; i < pathsLen; i++) { + pathsSize += paths[i] != null ? paths[i].length() : NULL.length(); + if (i > 0) { + pathsSize += 1; + } + } + if (pathsLen > 1) { + pathsSize += 2; + } + final StringBuilder sb = new StringBuilder( + operationName.length() + pathsSize + targetType.length() + 2); + sb.append(operationName); + sb.append(' '); + if (pathsLen > 1) { + sb.append('['); + } + for (int i = 0; i < pathsLen; i++) { + if (i > 0) { + sb.append(','); + } + sb.append(paths[i] != null ? paths[i] : NULL); + } + if (pathsLen > 1) { + sb.append(']'); + } + sb.append(' '); + sb.append(targetType); + return sb.toString(); + } + + /** + * Build message content for test failure log message. + * + * @param operation + * JSON patch operation being executed. + * @param path + * JSON patch operation source path. + * @param value + * Target value being modified. + * @return Log message content. + */ + protected String testMessage(final String operation, final String path, + final String value) { + final int tarLen = value != null + ? TEST_FAIL_ON1.length() + TEST_FAIL_ON2.length() + value.length() + : 0; + final StringBuilder sb = new StringBuilder( + operation.length() + TEST_FAIL_OP.length() + TEST_FAIL_FOR.length() + + path.length() + TEST_FAIL_FAI.length() + tarLen); + sb.append(operation); + sb.append(TEST_FAIL_OP); + sb.append(TEST_FAIL_FOR); + sb.append(path); + sb.append(TEST_FAIL_FAI); + if (tarLen > 0) { + sb.append(TEST_FAIL_ON1); + sb.append(value); + sb.append(TEST_FAIL_ON2); + } + return sb.toString(); + } + + /** + * Build message content for test failure log message. + * + * @param operation + * JSON patch operation being executed. + * @param paths + * JSON patch operation source paths. + * @param value + * Target value being modified. + * @return Log message content. + */ + protected String testMessage(final String operation, final String[] paths, + final String value) { + final int tarLen = value != null + ? TEST_FAIL_ON1.length() + TEST_FAIL_ON2.length() + value.length() + : 0; + final int pathsLen = paths != null ? paths.length : 0; + int pathsSize = 0; + for (int i = 0; i < pathsLen; i++) { + pathsSize += paths[i] != null ? paths[i].length() : NULL.length(); + if (i > 0) { + pathsSize += 1; + } + } + if (pathsLen > 1) { + pathsSize += 2; + } + final StringBuilder sb = new StringBuilder( + operation.length() + TEST_FAIL_OP.length() + TEST_FAIL_FOR.length() + + pathsSize + TEST_FAIL_FAI.length() + tarLen); + sb.append(operation); + sb.append(TEST_FAIL_OP); + sb.append(TEST_FAIL_FOR); + if (pathsLen > 1) { + sb.append('['); + } + for (int i = 0; i < pathsLen; i++) { + if (i > 0) { + sb.append(','); + } + sb.append(paths[i] != null ? paths[i] : NULL); + } + if (pathsLen > 1) { + sb.append(']'); + } + sb.append(TEST_FAIL_FAI); + if (tarLen > 0) { + sb.append(TEST_FAIL_ON1); + sb.append(value); + sb.append(TEST_FAIL_ON2); + } + return sb.toString(); + } + + /** + * Build message content for test failure log message. + * + * @param paths + * JSON patch operation source path. + * @param targetType + * Name of target (JSON value being modified) value type. + * @return Log message content. + */ + protected String testMessage(final String[] paths, final String targetType) { + final String operationName = operationName(); + final int tarLen = targetType != null + ? TEST_FAIL_ON1.length() + TEST_FAIL_ON2.length() + targetType.length() + : 0; + int pathsLen = 0; + for (int i = 0; i < paths.length; i++) { + pathsLen += paths[i] != null ? paths[i].length() : NULL.length(); + if (i > 0) { + pathsLen += 1; + } + } + if (paths.length > 1) { + pathsLen += 2; + } + final StringBuilder sb = new StringBuilder( + operationName.length() + TEST_FAIL_OP.length() + TEST_FAIL_FOR.length() + + pathsLen + TEST_FAIL_FAI.length() + tarLen); + sb.append(operationName); + sb.append(TEST_FAIL_OP); + sb.append(TEST_FAIL_FOR); + if (paths.length > 1) { + sb.append('['); + } + for (int i = 0; i < paths.length; i++) { + if (i > 0) { + sb.append(','); + } + sb.append(paths[i] != null ? paths[i] : NULL); + } + if (paths.length > 1) { + sb.append(']'); + } + sb.append(TEST_FAIL_FAI); + if (tarLen > 0) { + sb.append(TEST_FAIL_ON1); + sb.append(targetType); + sb.append(TEST_FAIL_ON2); + } + return sb.toString(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchCreate.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchCreate.java new file mode 100644 index 0000000..e5fc243 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchCreate.java
@@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatch; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * JavaScript Object Notation (JSON) compatibility tests: {@link JsonPatch} API + * factory methods added in JSON-P 1.1.<br> + */ +public class PatchCreate { + + /** + * Creates an instance of {@link JsonPatch} API factory methods added in + * JSON-P 1.1 test. + */ + PatchCreate() { + super(); + } + + /** + * Test {@link JsonPatch} factory method added in JSON-P 1.1. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonPatch API factory methods added in JSON-P 1.1."); + System.out.println("JsonPatch API factory methods added in JSON-P 1.1."); + testCreateDiff(result); + testCreatePatch(result); + testCreatePatchBuilder(result); + return result; + } + + /** + * Test {@link Json#createDiff(JsonStructure,JsonStructure)} method. + * + * @param result + * Test suite result. + */ + private void testCreateDiff(final TestResult result) { + System.out.println(" - Json#createDiff(JsonStructure,JsonStructure)"); + final JsonObject src = createSimpleObject(); + final JsonObject trg = createSimpleObjectWithStr(); + final JsonPatch patch = Json.createDiff(src, trg); + final JsonObject out = patch.apply(src); + if (operationFailed(trg, out)) { + result.fail("createDiff(JsonStructure,JsonStructure)", "Builder output " + + valueToString(out) + " value shall be " + valueToString(trg)); + } + } + + /** + * Test {@link Json#createPatch(JsonArray)} method. + * + * @param result + * Test suite result. + */ + private void testCreatePatch(final TestResult result) { + System.out.println(" - Json#createPatch(JsonArray)"); + final JsonObject src = createSimpleObject(); + final JsonObject trg = createSimpleObjectWithStr(); + final JsonArray patchArray = Json.createDiff(src, trg).toJsonArray(); + final JsonPatch patch = Json.createPatch(patchArray); + final JsonObject out = patch.apply(src); + if (operationFailed(trg, out)) { + result.fail("createPatch(JsonArray)", "Builder output " + + valueToString(out) + " value shall be " + valueToString(trg)); + } + } + + /** + * Test {@link Json#createPatchBuilder(JsonArray)} method. + * + * @param result + * Test suite result. + */ + private void testCreatePatchBuilder(final TestResult result) { + System.out.println(" - Json#createPatchBuilder(JsonArray)"); + final JsonObject src = createSimpleObject(); + final JsonObject trg = createSimpleObjectWithStr(); + final JsonArray patchArray = Json.createDiff(src, trg).toJsonArray(); + final JsonPatchBuilder patchBuilder = Json.createPatchBuilder(patchArray); + final JsonObject out = patchBuilder.build().apply(src); + if (operationFailed(trg, out)) { + result.fail("createPatchBuilder(JsonArray)", "Builder output " + + valueToString(out) + " value shall be " + valueToString(trg)); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null || !assertEquals(check, out); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationAdd.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationAdd.java new file mode 100644 index 0000000..7318284 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationAdd.java
@@ -0,0 +1,586 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.JsonValueType; +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatch; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.JsonValue; +import jakarta.json.JsonStructure; +import jakarta.json.Json; +import jakarta.json.JsonPointer; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * RFC 6902: JavaScript Object Notation (JSON) Patch compatibility tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>}. + * <p> + * Implements + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC 6902: + * 4.1. add</a>} tests. + */ +class PatchOperationAdd extends CommonOperation { + + /** Tested operation name. */ + private final String OPERATION = "ADD"; + + /** + * Creates an instance of RFC 6902 add operation test. + */ + PatchOperationAdd() { + super(); + } + + /** + * Test RFC 6902 add operation. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult("RFC 6902 add operation"); + System.out.println("Testing RFC 6902 add operation:"); + testAddStringOnEmptyObject(result); + testAddStringOnSimpleObject(result); + testAddStringOnEmptyArray(result); + testAddStringOnSimpleArray(result); + testAddStringOnSimpleArray2(result); + testAddIntOnEmptyObject(result); + testAddIntOnSimpleObject(result); + testAddIntOnEmptyArray(result); + testAddIntOnSimpleArray(result); + testAddIntOnSimpleArray2(result); + testAddBooleanOnEmptyObject(result); + testAddBooleanOnSimpleObject(result); + testAddBooleanOnEmptyArray(result); + testAddBooleanOnSimpleArray(result); + testAddBooleanOnSimpleArray2(result); + testAddObjectOnEmptyObject(result); + testAddObjectOnSimpleObject(result); + testAddObjectOnEmptyArray(result); + testAddObjectOnSimpleArray(result); + testAddObjectOnSimpleArray2(result); + testAddArrayToReplaceObject(result); + testAddArrayToReplaceDocument(result); + testAddStringArrayToStringArray(result); + testAddStringToNonExistingObject(result); + return result; + } + + /** + * Test RFC 6902 add operation for {@code String} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testAddStringOnEmptyObject(final TestResult result) { + System.out.println(" - for String on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject check = createSimpleObjectStr(); + simpleOperation(result, in, check, STR_PATH, STR_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code String} on empty JSON array. Only + * allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testAddStringOnEmptyArray(final TestResult result) { + System.out.println(" - for String on empty JSON array"); + final JsonArray in = createEmptyArray(); + final JsonArray check = createEmptyArrayWithStr(); + simpleOperation(result, in, check, "/0", STR_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testAddStringOnSimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject check = createSimpleObjectWithStr(); + simpleOperation(result, in, check, STR_PATH, STR_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code String} on simple JSON array. Using + * index {@code 0} to add {@code String} before already existing element and + * index {@code 1} to add {@code String} after already existing element. + * + * @param result + * Tests result record. + */ + private void testAddStringOnSimpleArray(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 1"); + final JsonArray in = createStringArray1(); + final JsonArray checkBefore = createSimpleStringArrayWithStrBefore(); + final JsonArray checkAfter = createSimpleStringArrayWithStrAfter(); + // Add before. + simpleOperation(result, in, checkBefore, "/0", STR_VALUE); + // Add after. + simpleOperation(result, in, checkAfter, "/1", STR_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code String}s on simple JSON array. + * Starting with an array of size 2. + * <ul> + * <li>Adding {@code String} at the end, in the middle and at the beginning of + * this array. + * <li>Adding {@code String} at the beginning, in the middle and at the end of + * this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testAddStringOnSimpleArray2(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 2"); + final JsonArray in = createStringArray2(); + final JsonArray check = createSimpleStringArray5(); + complexOperation(result, in, check, new String[] { "/2", "/1", "/0" }, + new String[] { STR_VALUE_5, STR_VALUE_3, STR_VALUE_1 }); + complexOperation(result, in, check, new String[] { "/0", "/2", "/4" }, + new String[] { STR_VALUE_1, STR_VALUE_3, STR_VALUE_5 }); + } + + /** + * Test RFC 6902 add operation for {@code int} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testAddIntOnEmptyObject(final TestResult result) { + System.out.println(" - for int on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject check = createSimpleObjectInt(); + simpleOperation(result, in, check, INT_PATH, INT_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code int} on empty JSON array. Only + * allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testAddIntOnEmptyArray(final TestResult result) { + System.out.println(" - for int on empty JSON array"); + final JsonArray in = createEmptyArray(); + final JsonArray check = createEmptyArrayWithInt(); + simpleOperation(result, in, check, "/0", INT_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testAddIntOnSimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject check = createSimpleObjectWithInt(); + simpleOperation(result, in, check, INT_PATH, INT_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code int} on simple JSON array. Using + * index {@code 0} to add {@code int} before already existing element and + * index {@code 1} to add {@code int} after already existing element. + * + * @param result + * Tests result record. + */ + private void testAddIntOnSimpleArray(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 1"); + final JsonArray in = createIntArray1(); + final JsonArray checkBefore = createSimpleIntArrayWithIntBefore(); + final JsonArray checkAfter = createSimpleIntArrayWithIntAfter(); + // Add before. + simpleOperation(result, in, checkBefore, "/0", INT_VALUE); + // Add after. + simpleOperation(result, in, checkAfter, "/1", INT_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code int}s on simple JSON array. Starting + * with an array of size 2. + * <ul> + * <li>Adding {@code int} at the end, in the middle and at the beginning of + * this array. + * <li>Adding {@code int} at the beginning, in the middle and at the end of + * this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testAddIntOnSimpleArray2(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 2"); + final JsonArray in = createIntArray2(); + final JsonArray check = createSimpleIntArray5(); + complexOperation(result, in, check, new String[] { "/2", "/1", "/0" }, + new Integer[] { INT_VALUE_5, INT_VALUE_3, INT_VALUE_1 }); + complexOperation(result, in, check, new String[] { "/0", "/2", "/4" }, + new Integer[] { INT_VALUE_1, INT_VALUE_3, INT_VALUE_5 }); + } + + /** + * Test RFC 6902 add operation for {@code boolean} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testAddBooleanOnEmptyObject(final TestResult result) { + System.out.println(" - for boolean on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject check = createSimpleObjectBool(); + simpleOperation(result, in, check, BOOL_PATH, BOOL_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code boolean} on empty JSON array. Only + * allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testAddBooleanOnEmptyArray(final TestResult result) { + System.out.println(" - for boolean on empty JSON array"); + final JsonArray in = createEmptyArray(); + final JsonArray check = createEmptyArrayWithBool(); + simpleOperation(result, in, check, "/0", BOOL_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testAddBooleanOnSimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject check = createSimpleObjectWithBool(); + simpleOperation(result, in, check, BOOL_PATH, BOOL_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code boolean} on simple JSON array. Using + * index {@code 0} to add {@code boolean} before already existing element and + * index {@code 1} to add {@code boolean} after already existing element. + * + * @param result + * Tests result record. + */ + private void testAddBooleanOnSimpleArray(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 1"); + final JsonArray in = createBoolArray1(); + final JsonArray checkBefore = createSimpleBoolArrayWithBoolBefore(); + final JsonArray checkAfter = createSimpleBoolArrayWithBoolAfter(); + // Add before. + simpleOperation(result, in, checkBefore, "/0", BOOL_FALSE); + // Add after. + simpleOperation(result, in, checkAfter, "/1", BOOL_FALSE); + } + + /** + * Test RFC 6902 add operation for {@code boolean}s on simple JSON array. + * Starting with an array of size 2. + * <ul> + * <li>Adding {@code boolean} at the end, in the middle and at the beginning + * of this array. + * <li>Adding {@code boolean} at the beginning, in the middle and at the end + * of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testAddBooleanOnSimpleArray2(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 2"); + final JsonArray in = createBoolArray2(); + final JsonArray check = createSimpleBoolArray5(); + complexOperation(result, in, check, new String[] { "/2", "/1", "/0" }, + new Boolean[] { BOOL_TRUE, BOOL_TRUE, BOOL_FALSE }); + complexOperation(result, in, check, new String[] { "/0", "/2", "/4" }, + new Boolean[] { BOOL_FALSE, BOOL_TRUE, BOOL_TRUE }); + } + + /** + * Test RFC 6902 add operation for {@code JsonObject} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testAddObjectOnEmptyObject(final TestResult result) { + System.out.println(" - for JsonObject on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject check = createSimpleObjectObject(); + simpleOperation(result, in, check, OBJ_PATH, OBJ_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code JsonObject} on empty JSON array. + * Only allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testAddObjectOnEmptyArray(final TestResult result) { + System.out.println(" - for JsonObject on empty JSON array"); + final JsonArray in = createEmptyArray(); + final JsonArray check = createEmptyArrayWithObject(); + simpleOperation(result, in, check, "/0", OBJ_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code JsonObject} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testAddObjectOnSimpleObject(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON object"); + final JsonObject in = createCompoundObject(); + final JsonObject check = createCompoundObjectWithObject(); + simpleOperation(result, in, check, OBJ_PATH, OBJ_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code JsonObject} on simple JSON array. + * Using index {@code 0} to add {@code JsonObject} before already existing + * element and index {@code 1} to add {@code JsonObject} after already + * existing element. + * + * @param result + * Tests result record. + */ + private void testAddObjectOnSimpleArray(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 1"); + final JsonArray in = createObjectArray1(); + final JsonArray checkBefore = createSimpleObjectArrayWithObjectBefore(); + final JsonArray checkAfter = createSimpleObjectArrayWithObjectAfter(); + // Add before. + simpleOperation(result, in, checkBefore, "/0", OBJ_VALUE); + // Add after. + simpleOperation(result, in, checkAfter, "/1", OBJ_VALUE); + } + + /** + * Test RFC 6902 add operation for {@code JsonObject}s on simple JSON array. + * Starting with an array of size 2. + * <ul> + * <li>Adding {@code JsonObject} at the end, in the middle and at the + * beginning of this array. + * <li>Adding {@code JsonObject} at the beginning, in the middle and at the + * end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testAddObjectOnSimpleArray2(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 2"); + final JsonArray in = createObjectArray2(); + final JsonArray check = createSimpleObjectArray5(); + complexOperation(result, in, check, new String[] { "/2", "/1", "/0" }, + new JsonObject[] { OBJ_VALUE_5, OBJ_VALUE_3, OBJ_VALUE_1 }); + complexOperation(result, in, check, new String[] { "/0", "/2", "/4" }, + new JsonObject[] { OBJ_VALUE_1, OBJ_VALUE_3, OBJ_VALUE_5 }); + } + + // Tests based on RFC 6902 definitions and examples. + + /** + * Test that existing target object is replaced by specified array when ADD + * operation is applied. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC 6902: + * 4.1. add</a>}:<br> + * When the operation is applied, the target location MUST reference one of: + * <ul> + * <li>A member to add to an existing object - whereupon the supplied value is + * added to that object at the indicated location. If the member already + * exists, it is replaced by the specified value.</li> + * <li>...</li> + * </ul> + */ + private void testAddArrayToReplaceObject(final TestResult result) { + System.out.println(" - for JsonArray to replace JsonObject"); + final JsonObject in = createCompoundObject(); + final JsonObject check = createCompoundObjectWithObjectReplaced(); + final JsonArray value = createSimpleStringArray5(); + simpleOperation(result, in, check, DEF_OBJ_PATH, value); + } + + /** + * Test that whole document is replaced by specified array when ADD operation + * is applied with root pointer. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC 6902: + * 4.1. add</a>}:<br> + * When the operation is applied, the target location MUST reference one of: + * <ul> + * <li>The root of the target document - whereupon the specified value becomes + * the entire content of the target document.</li> + * <li>...</li> + * </ul> + */ + private void testAddArrayToReplaceDocument(final TestResult result) { + System.out.println(" - for JsonArray to replace whole document"); + final JsonObject in = createCompoundObject(); + final JsonArray check = createSimpleStringArray5(); + final JsonArray value = createSimpleStringArray5(); + // Instance being replaced is JsonObject, instance being added is JsonArray. + // The only API method allowing + // this is the one working with JsonStructure. New builder instance is used + // for each of the cases. + final JsonPatch patch1 = builderAdd(Json.createPatchBuilder(), "", value) + .build(); + final JsonValue out1 = patch1.apply((JsonStructure) in); + if (!assertEquals(check, out1)) { + final String className = value.getClass().getSimpleName(); + result.fail("ADD " + className + " to compound object", + "ADD operation for " + className + " failed on compound value"); + } + } + + /** + * Test ADD operation of an array of {@code String}s into existing array of + * {@code String}s. This scenario is inspired by + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC 6902: + * 4.1. add</a>} operation example {@code { "op": "add", "path": "/a/b/c", + * "value": [ "foo", "bar" ] }} and following explanation of this operation on + * an array: + * <ul> + * <li>An element to add to an existing array - whereupon the supplied value + * is added to the array at the indicated location. Any elements at or above + * the specified index are shifted one position to the right. The specified + * index MUST NOT be greater than the number of elements in the array. If the + * "-" character is used to index the end of the array (see [RFC6901]), this + * has the effect of appending the value to the array.</li> + * </ul> + */ + private void testAddStringArrayToStringArray(final TestResult result) { + System.out.println(" - for String array to be added to existing String array"); + final JsonArray in = createStringArray2(); + final JsonArray check = createStringArray2WithStringArrayInTheMiddle(); + final JsonArray value = createStringInnerArray2(); + simpleOperation(result, in, check, "/1", value); + } + + /** + * Test ADD operation on non existing JsonObject. This scenario is described + * in {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC + * 6902: 4.1. add</a>} error handling samples. Test is trying to ADD value { + * "address" : "In a galaxy far far away"} into object { "name" : "John Smith" + * } using path "/child/address". Even "/child" path does not exist so this + * operation must fail. + * + */ + private void testAddStringToNonExistingObject(final TestResult result) { + System.out.println(" - for String to be added to non existing JsonObject"); + final JsonObject in = createSimpleObject(); + final JsonValue value = Json.createValue(STR_VALUE); + final String path = DEF_OBJ_PATH + STR_PATH; + final JsonPointer ptr = Json.createPointer(path); + simpleOperationFail(result, in, path, value); + } + + /** + * Tested operation name {@code "MOVE"}. + * + * @return Operation name to be used in logs. + */ + @Override + protected String operationName() { + return OPERATION; + } + + /** + * Create and initialize patch builder to contain ADD operation to be applied. + * + * @param path + * JSON path of value to be added. + * @param value + * JSON Value to be added. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder createOperationBuilder(final String path, + final Object value) { + return builderAdd(Json.createPatchBuilder(), path, value); + } + + /** + * Update patch builder to contain next ADD operation to be applied. + * + * @param builder + * JSON patch builder to update. + * @param path + * JSON path of value to be added. + * @param value + * JSON Value to be added. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder updateOperationBuilder( + final JsonPatchBuilder builder, final String path, final Object value) { + return builderAdd(builder, path, value); + } + + /** + * Add {@code value} at {@code path} to provided JSON patch builder. + * + * @param builder + * Target JSON patch builder. + * @param path + * JSON path of value to be added. + * @param value + * Value to be added at given JSON path. + * @return JSON patch builder containing new {@code value} at {@code path} + * added. + */ + @SuppressWarnings("UnnecessaryUnboxing") + private static JsonPatchBuilder builderAdd(final JsonPatchBuilder builder, + final String path, final Object value) { + switch (JsonValueType.getType(value.getClass())) { + case String: + return builder.add(path, (String) value); + case Integer: + return builder.add(path, ((Integer) value).intValue()); + case Boolean: + return builder.add(path, ((Boolean) value).booleanValue()); + case JsonValue: + return builder.add(path, (JsonValue) value); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationCopy.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationCopy.java new file mode 100644 index 0000000..f0765c6 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationCopy.java
@@ -0,0 +1,298 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatchBuilder; + +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * RFC 6902: JavaScript Object Notation (JSON) Patch compatibility tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>}. + * <p> + * Implements + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.5">RFC 6902: + * 4.5. copy</a>} tests. + */ +public class PatchOperationCopy extends CommonOperation { + + /** Tested operation name. */ + private final String OPERATION = "COPY"; + + /** + * Creates an instance of RFC 6902 replace operation test. + */ + PatchOperationCopy() { + super(); + } + + /** + * Test RFC 6902 COPY operation. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult("RFC 6902 copy operation"); + System.out.println("Testing RFC 6902 copy operation:"); + testCopyStringOnSimpleObject(result); + testCopyStringOnSimpleArray(result); + testCopyIntOnSimpleObject(result); + testCopyIntOnSimpleArray(result); + testCopyBoolOnSimpleObject(result); + testCopyBoolOnSimpleArray(result); + testCopyObjectOnSimpleObject(result); + testCopyObjectOnSimpleArray(result); + testCopyStringOnCompoundObject(result); + testCopyOfNonExistingLocationInObject(result); + testCopyOfNonExistingLocationInArray(result); + + return result; + } + + /** + * Test RFC 6902 COPY operation for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testCopyStringOnSimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObjectStr(); + final JsonObject check = createSimpleObjectCopyStr(); + simpleOperation(result, in, check, STR_PATH, DEF_PATH); + } + + /** + * Test RFC 6902 COPY operation for {@code String} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testCopyStringOnSimpleArray(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 2"); + final JsonArray in = createStringArray2(); + simpleOperation(result, in, createStringArray2Copy1to0(), "/1", "/0"); + simpleOperation(result, in, createStringArray2Copy0to2(), "/0", "/2"); + simpleOperation(result, in, createStringArray2Copy0to1(), "/0", "/1"); + } + + /** + * Test RFC 6902 COPY operation for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testCopyIntOnSimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObjectInt(); + final JsonObject check = createSimpleObjectCopyInt(); + simpleOperation(result, in, check, INT_PATH, DEF_PATH); + } + + /** + * Test RFC 6902 COPY operation for {@code int} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testCopyIntOnSimpleArray(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 2"); + final JsonArray in = createIntArray2(); + simpleOperation(result, in, createIntArray2Copy1to0(), "/1", "/0"); + simpleOperation(result, in, createIntArray2Copy0to2(), "/0", "/2"); + simpleOperation(result, in, createIntArray2Copy0to1(), "/0", "/1"); + } + + /** + * Test RFC 6902 COPY operation for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testCopyBoolOnSimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObjectBool(); + final JsonObject check = createSimpleObjectCopyBool(); + simpleOperation(result, in, check, BOOL_PATH, DEF_PATH); + } + + /** + * Test RFC 6902 COPY operation for {@code boolean} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testCopyBoolOnSimpleArray(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 2"); + final JsonArray in = createBoolArray2(); + simpleOperation(result, in, createBoolArray2Copy1to0(), "/1", "/0"); + simpleOperation(result, in, createBoolArray2Copy0to2(), "/0", "/2"); + simpleOperation(result, in, createBoolArray2Copy0to1(), "/0", "/1"); + } + + /** + * Test RFC 6902 COPY operation for {@code JsonObject} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testCopyObjectOnSimpleObject(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON object"); + final JsonObject in = createSimpleObjectObject(); + final JsonObject check = createSimpleObjectCopyObject(); + simpleOperation(result, in, check, OBJ_PATH, DEF_PATH); + } + + /** + * Test RFC 6902 COPY operation for {@code JsonObject} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testCopyObjectOnSimpleArray(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 2"); + final JsonArray in = createObjectArray2(); + simpleOperation(result, in, createObjectArray2Copy1to0(), "/1", "/0"); + simpleOperation(result, in, createObjectArray2Copy0to2(), "/0", "/2"); + simpleOperation(result, in, createObjectArray2Copy0to1(), "/0", "/1"); + } + + /** + * Test RFC 6902 COPY operation for {@code String} on compound JSON object. + * Copied value overwrites an existing value. + * + * @param result + * Tests result record. + */ + private void testCopyStringOnCompoundObject(final TestResult result) { + System.out.println(" - for String on compound JSON object"); + final JsonObject in = createCompoundObject(); + final JsonObject check = createCompoundObjectCopyValue(); + simpleOperation(result, in, check, DEF_PATH, DEF_OBJ_PATH + DEF_PATH); + } + + // Tests based on RFC 6902 definitions and examples. + + /** + * Test RFC 6902 COPY operation for non existing location in object. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.4">RFC 6902: + * 4.5. copy</a>} defines:<br> + * The "from" location MUST exist for the operation to be successful. + */ + private void testCopyOfNonExistingLocationInObject(final TestResult result) { + System.out.println(" - for non existing location in JsonObject"); + final JsonObject[] objsIn = new JsonObject[] { createEmptyObject(), + createSimpleObject(), createCompoundObject() }; + final String[] paths = new String[] { STR_PATH, INT_PATH, BOOL_PATH, + OBJ_PATH }; + final Object[] values = new Object[] { OBJ_PATH, BOOL_PATH, INT_PATH, + STR_PATH }; + // Go trough all objects + for (int i = 0; i < objsIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + simpleOperationFail(result, objsIn[i], paths[j], values[i]); + } + } + } + + /** + * Test RFC 6902 COPY operation for non existing location in array. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.4">RFC 6902: + * 4.5. copy</a>} defines:<br> + * The "from" location MUST exist for the operation to be successful. + */ + private void testCopyOfNonExistingLocationInArray(final TestResult result) { + System.out.println(" - for non existing location in JsonArray"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray1(), createIntArray2(), createSimpleBoolArray5(), + createObjectArray2() }; + final String[] paths = new String[] { "/", "/-1", "/-", "/5", "/0a", "/42", + STR_PATH + "/0" }; + final Object[] values = new Object[] { "/0", "/1", "/2", "/5", "/1" }; + // Go trough all arrays + for (int i = 0; i < arraysIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + simpleOperationFail(result, arraysIn[i], paths[j], values[i]); + } + } + } + + /** + * Tested operation name {@code "COPY"}. + * + * @return Operation name to be used in logs. + */ + @Override + protected String operationName() { + return OPERATION; + } + + /** + * Create and initialize patch builder to contain COPY operation to be + * applied. + * + * @param path + * Source JSON path of COPY operation. + * @param value + * Target JSON path of COPY operation. Must be instance of + * {@link String}. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder createOperationBuilder(final String path, + final Object value) { + if (value instanceof String) { + // System.out.println(" COPY "+path+" -> "+(String)value); + return Json.createPatchBuilder().copy((String) value, path); + } else { + throw new IllegalArgumentException( + "Argument \"value\" is not an instance of String"); + } + } + + /** + * Update patch builder to contain next COPY operation to be applied. + * + * @param builder + * JSON patch builder to update. + * @param path + * Source JSON path of COPY operation. + * @param value + * Target JSON path of COPY operation. Must be instance of + * {@link String}. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder updateOperationBuilder( + final JsonPatchBuilder builder, final String path, final Object value) { + if (value instanceof String) { + // System.out.println(" COPY "+path+" -> "+(String)value); + return builder.copy((String) value, path); + } else { + throw new IllegalArgumentException( + "Argument \"value\" is not an instance of String"); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationEnum.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationEnum.java new file mode 100644 index 0000000..82f0c6b --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationEnum.java
@@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.JsonPatch; + +// $Id$ +/** + * RFC 6902: JavaScript Object Notation (JSON) Patch compatibility tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>}. + * <p> + * Test {@link JsonPatch.Operation} enumeration. + */ +public class PatchOperationEnum { + + /** + * Creates an instance of {@link JsonPatch.Operation} enumeration test. + */ + PatchOperationEnum() { + super(); + } + + /** + * Test {@link JsonPatch.Operation} enumeration. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "JsonPatch.Operation enumeration test"); + System.out.println("JsonPatch.Operation enumeration test"); + testOperationName(result); + testOperationValueOf(result); + return result; + } + + /** + * Test {@link JsonPatch.Operation#fromOperationName(String)} and + * {@link JsonPatch.Operation#operationName()} methods. + * + * @param result + * Tests result record. + */ + private void testOperationName(final TestResult result) { + System.out.println(" - fromOperationName(String) and operationName(String)"); + for (final JsonPatch.Operation op : JsonPatch.Operation.values()) { + final String opName = op.operationName(); + final JsonPatch.Operation opOut = JsonPatch.Operation + .fromOperationName(opName); + final int opNameLen = opName.length(); + boolean opNameLc = true; + for (int i = 0; opNameLc && i < opNameLen; i++) { + opNameLc = Character.isLowerCase(opName.charAt(i)); + } + if (!opNameLc) { + result.fail("operationName(String)", + "Returned value " + opName + " is not lower case String"); + } + if (op != opOut) { + result.fail("fromOperationName(String) and operationName(String)", + "Returned operation " + opOut.name() + " shall be " + op.name()); + } + } + } + + /** + * Test {@code JsonPatch.Operation#valueOf(String)} method. + * + * @param result + * Tests result record. + */ + private void testOperationValueOf(final TestResult result) { + System.out.println(" - valueOf(String)"); + for (final JsonPatch.Operation op : JsonPatch.Operation.values()) { + final String opName = op.name(); + final JsonPatch.Operation opOut = JsonPatch.Operation.valueOf(opName); + if (op != opOut) { + result.fail("valueOf(String)", + "Returned operation " + opOut.name() + " shall be " + op.name()); + } + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationMove.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationMove.java new file mode 100644 index 0000000..0286f52 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationMove.java
@@ -0,0 +1,455 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatch; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.JsonPointer; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * RFC 6902: JavaScript Object Notation (JSON) Patch compatibility tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>}. + * <p> + * Implements + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.4">RFC 6902: + * 4.4. move</a>} tests. + */ +public class PatchOperationMove extends CommonOperation { + + /** Tested operation name. */ + private final String OPERATION = "MOVE"; + + /** + * Creates an instance of RFC 6902 replace operation test. + */ + PatchOperationMove() { + super(); + } + + /** + * Test RFC 6902 MOVE operation. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult("RFC 6902 move operation"); + System.out.println("Testing RFC 6902 move operation:"); + testMoveStringOnSimpleObject(result); + testMoveStringOnSimpleArray(result); + testMoveStringOnSimpleArray2(result); + testMoveIntOnSimpleObject(result); + testMoveIntOnSimpleArray(result); + testMoveIntOnSimpleArray2(result); + testMoveBoolOnSimpleObject(result); + testMoveBoolOnSimpleArray(result); + testMoveBoolOnSimpleArray2(result); + testMoveObjectOnSimpleObject(result); + testMoveObjectOnSimpleArray(result); + testMoveObjectOnSimpleArray2(result); + testMoveStringOnCompoundObject(result); + testMoveOfNonExistingLocationInObject(result); + testMoveOfNonExistingLocationInArray(result); + testMoveVsRemoveAddOnSelfContainedPath(result); + return result; + } + + /** + * Test RFC 6902 MOVE operation for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testMoveStringOnSimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObjectStr(); + final JsonObject check = createSimpleObjectMoveStr(); + simpleOperation(result, in, check, STR_PATH, DEF_PATH); + } + + /** + * Test RFC 6902 MOVE operation for {@code String} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testMoveStringOnSimpleArray(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 2"); + final JsonArray in = createStringArray2(); + final JsonArray check = createStringArray2R(); + simpleOperation(result, in, in, "/0", "/0"); + simpleOperation(result, in, check, "/1", "/0"); + simpleOperation(result, in, check, "/0", "/1"); + simpleOperation(result, in, check, "/0", "/-"); + } + + /** + * Test RFC 6902 MOVE operation for {@code String} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testMoveStringOnSimpleArray2(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 5"); + final JsonArray in = createSimpleStringArray5(); + final JsonArray check = createSimpleStringArray5R(); + complexOperation(result, in, check, new String[] { "/3", "/0", "/3", "/4" }, + new String[] { "/1", "/2", "/1", "/0" }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/0", "/2" }, + new String[] { "/-", "/2", "/3", "/0" }); + } + + /** + * Test RFC 6902 MOVE operation for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testMoveIntOnSimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObjectInt(); + final JsonObject check = createSimpleObjectMoveInt(); + simpleOperation(result, in, check, INT_PATH, DEF_PATH); + } + + /** + * Test RFC 6902 MOVE operation for {@code int} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testMoveIntOnSimpleArray(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 2"); + final JsonArray in = createIntArray2(); + final JsonArray check = createIntArray2R(); + simpleOperation(result, in, in, "/0", "/0"); + simpleOperation(result, in, check, "/1", "/0"); + simpleOperation(result, in, check, "/0", "/1"); + simpleOperation(result, in, check, "/0", "/-"); + } + + /** + * Test RFC 6902 MOVE operation for {@code int} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testMoveIntOnSimpleArray2(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 5"); + final JsonArray in = createSimpleIntArray5(); + final JsonArray check = createSimpleIntArray5R(); + complexOperation(result, in, check, new String[] { "/3", "/0", "/3", "/4" }, + new String[] { "/1", "/2", "/1", "/0" }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/0", "/2" }, + new String[] { "/-", "/2", "/3", "/0" }); + } + + /** + * Test RFC 6902 MOVE operation for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testMoveBoolOnSimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObjectBool(); + final JsonObject check = createSimpleObjectMoveBool(); + simpleOperation(result, in, check, BOOL_PATH, DEF_PATH); + } + + /** + * Test RFC 6902 MOVE operation for {@code boolean} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testMoveBoolOnSimpleArray(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 2"); + final JsonArray in = createBoolArray2(); + final JsonArray check = createBoolArray2R(); + simpleOperation(result, in, in, "/0", "/0"); + simpleOperation(result, in, check, "/1", "/0"); + simpleOperation(result, in, check, "/0", "/1"); + simpleOperation(result, in, check, "/0", "/-"); + } + + /** + * Test RFC 6902 MOVE operation for {@code boolean} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testMoveBoolOnSimpleArray2(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 5"); + final JsonArray in = createSimpleBoolArray5(); + final JsonArray check = createSimpleBoolArray5R(); + complexOperation(result, in, check, new String[] { "/3", "/0", "/3", "/4" }, + new String[] { "/1", "/2", "/1", "/0" }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/0", "/2" }, + new String[] { "/-", "/2", "/3", "/0" }); + } + + /** + * Test RFC 6902 MOVE operation for {@code JsonObject} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testMoveObjectOnSimpleObject(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON object"); + final JsonObject in = createSimpleObjectObject(); + final JsonObject check = createSimpleObjectMoveObject(); + simpleOperation(result, in, check, OBJ_PATH, DEF_PATH); + } + + /** + * Test RFC 6902 MOVE operation for {@code JsonObject} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testMoveObjectOnSimpleArray(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 2"); + final JsonArray in = createObjectArray2(); + final JsonArray check = createObjectArray2R(); + simpleOperation(result, in, in, "/0", "/0"); + simpleOperation(result, in, check, "/1", "/0"); + simpleOperation(result, in, check, "/0", "/1"); + simpleOperation(result, in, check, "/0", "/-"); + } + + /** + * Test RFC 6902 MOVE operation for {@code JsonObject} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testMoveObjectOnSimpleArray2(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 5"); + final JsonArray in = createSimpleObjectArray5(); + final JsonArray check = createSimpleObjectArray5R(); + complexOperation(result, in, check, new String[] { "/3", "/0", "/3", "/4" }, + new String[] { "/1", "/2", "/1", "/0" }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/0", "/2" }, + new String[] { "/-", "/2", "/3", "/0" }); + } + + /** + * Test RFC 6902 MOVE operation for {@code String} on compound JSON object. + * Moved value overwrites an existing value. + * + * @param result + * Tests result record. + */ + private void testMoveStringOnCompoundObject(final TestResult result) { + System.out.println(" - for String on compound JSON object"); + final JsonObject in = createCompoundObject(); + final JsonObject check = createCompoundObjectMoveValue(); + simpleOperation(result, in, check, DEF_PATH, DEF_OBJ_PATH + DEF_PATH); + } + + // Tests based on RFC 6902 definitions and examples. + + /** + * Test RFC 6902 MOVE operation for non existing location in object. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.4">RFC 6902: + * 4.4. move</a>} defines:<br> + * The "from" location MUST exist for the operation to be successful. + */ + private void testMoveOfNonExistingLocationInObject(final TestResult result) { + System.out.println(" - for non existing location in JsonObject"); + final JsonObject[] objsIn = new JsonObject[] { createEmptyObject(), + createSimpleObject(), createCompoundObject() }; + final String[] paths = new String[] { STR_PATH, INT_PATH, BOOL_PATH, + OBJ_PATH }; + final Object[] values = new Object[] { OBJ_PATH, BOOL_PATH, INT_PATH, + STR_PATH }; + // Go trough all objects + for (int i = 0; i < objsIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + simpleOperationFail(result, objsIn[i], paths[j], values[i]); + } + } + } + + /** + * Test RFC 6902 MOVE operation for non existing location in array. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.4">RFC 6902: + * 4.4. move</a>} defines:<br> + * The "from" location MUST exist for the operation to be successful. + */ + private void testMoveOfNonExistingLocationInArray(final TestResult result) { + System.out.println(" - for non existing location in JsonArray"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray1(), createIntArray2(), createSimpleBoolArray5(), + createObjectArray2() }; + final String[] paths = new String[] { "/", "/-1", "/-", "/5", "/0a", "/42", + STR_PATH + "/0" }; + final Object[] values = new Object[] { "/0", "/1", "/2", "/5", "/1" }; + // Go trough all arrays + for (int i = 0; i < arraysIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + simpleOperationFail(result, arraysIn[i], paths[j], values[i]); + } + } + } + + /** + * Test RFC 6902 MOVE operation for moving existing path into path containing + * source path as a prefix. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.4">RFC 6902: + * 4.4. move</a>} defines:<br> + * This operation is functionally identical to a "remove" operation on the + * "from" location, followed immediately by an "add" operation at the target + * location with the value that was just removed. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-7">RFC 6901: 7. + * Error Handling</a>} defines:<br> + * This specification does not define how errors are handled. An application + * of JSON Pointer SHOULD specify the impact and handling of each type of + * error.<br> + * For example, some applications might stop pointer processing upon an error, + * while others may attempt to recover from missing values by inserting + * default ones.<br> + * This means, that such an operation may fail on non existing target "path" + * after ADD operation, but also missing pointer error recovery may take care + * of creating missing "path" elements. In both cases MOVE and sequence of + * REMOVE and ADD operations MUST produce the same result. + */ + private void testMoveVsRemoveAddOnSelfContainedPath(final TestResult result) { + System.out.println(" - for moving JsonObject under itself"); + final JsonObject in = createCompoundObject(); + final String targetPath = DEF_OBJ_PATH + DEF_PATH; + final JsonPointer ptr = Json.createPointer(DEF_OBJ_PATH); + final JsonValue value = ptr.getValue(in); + final JsonPatchBuilder moveBuilder = Json.createPatchBuilder() + .move(targetPath, DEF_OBJ_PATH); + final JsonPatchBuilder remAddBuilder = Json.createPatchBuilder() + .remove(DEF_OBJ_PATH).add(targetPath, value); + final JsonPatch movePatch = moveBuilder.build(); + final JsonPatch remAddPatch = remAddBuilder.build(); + // Check REMOVE and ADD sequence first. + JsonObject remAddOut; + try { + + remAddOut = remAddPatch.apply(in); + System.out.println(" REMOVE and ADD passed"); + } catch (JsonException e) { + remAddOut = null; + System.out.println(" REMOVE and ADD failed: " + e.getMessage()); + } + // Check MOVE second + JsonObject moveOut; + try { + moveOut = movePatch.apply(in); + System.out.println(" MOVE passed"); + } catch (JsonException e) { + moveOut = null; + System.out.println(" MOVE failed: " + e.getMessage()); + } + // Results evaluation + if (remAddOut != null) { + // Both output values are not null: Compare them + if (moveOut != null) { + if (!assertEquals(remAddOut, moveOut)) { + result.fail("MOVE vs REMOVE and ADD", + "Returned values are not equal"); + } + // REMOVE and ADD output is not null but MOVE output is null + } else { + result.fail("MOVE vs REMOVE and ADD", + "REMOVE and ADD failed but MOVE dit not"); + } + } else { + // REMOVE and ADD output is null but MOVE output is not null + if (moveOut != null) { + result.fail("MOVE vs REMOVE and ADD", + "MOVE failed but REMOVE and ADD dit not"); + } + // else: Both output values are null: both patch operations failed -> test + // passed + } + } + + /** + * Tested operation name {@code "MOVE"}. + * + * @return Operation name to be used in logs. + */ + @Override + protected String operationName() { + return OPERATION; + } + + /** + * Create and initialize patch builder to contain MOVE operation to be + * applied. + * + * @param path + * Source JSON path of MOVE operation. + * @param value + * Target JSON path of MOVE operation. Must be instance of + * {@link String}. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder createOperationBuilder(final String path, + final Object value) { + if (value instanceof String) { + // System.out.println(" MOVE "+path+" -> "+(String)value); + return Json.createPatchBuilder().move((String) value, path); + } else { + throw new IllegalArgumentException( + "Argument \"value\" is not an instance of String"); + } + } + + /** + * Update patch builder to contain next MOVE operation to be applied. + * + * @param builder + * JSON patch builder to update. + * @param path + * Source JSON path of MOVE operation. + * @param value + * Target JSON path of MOVE operation. Must be instance of + * {@link String}. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder updateOperationBuilder( + final JsonPatchBuilder builder, final String path, final Object value) { + if (value instanceof String) { + // System.out.println(" MOVE "+path+" -> "+(String)value); + return builder.move((String) value, path); + } else { + throw new IllegalArgumentException( + "Argument \"value\" is not an instance of String"); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationRemove.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationRemove.java new file mode 100644 index 0000000..a19b362 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationRemove.java
@@ -0,0 +1,491 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatchBuilder; + +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/* + * RFC 6902: JavaScript Object Notation (JSON) Patch compatibility tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>}. + * <p> + * Implements {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.2">RFC 6902: 4.2. remove</a>} + * tests. + */ +public class PatchOperationRemove extends CommonOperation { + + /** Tested operation name. */ + private final String OPERATION = "REMOVE"; + + /** + * Creates an instance of RFC 6902 remove operation test. + */ + PatchOperationRemove() { + super(); + } + + /** + * Test RFC 6902 remove operation. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult("RFC 6902 remove operation"); + System.out.println("Testing RFC 6902 remove operation:"); + testRemoveStringOnEmptyObject(result); + testRemoveStringOnEmptyArray(result); + testRemoveStringOnSimpleObject(result); + testRemoveStringOnSimpleArray(result); + testRemoveStringOnSimpleArray2(result); + testRemoveIntOnEmptyObject(result); + testRemoveIntOnEmptyArray(result); + testRemoveIntOnSimpleObject(result); + testRemoveIntOnSimpleArray(result); + testRemoveIntOnSimpleArray2(result); + testRemoveBoolOnEmptyObject(result); + testRemoveBoolOnEmptyArray(result); + testRemoveBoolOnSimpleObject(result); + testRemoveBoolOnSimpleArray(result); + testRemoveBoolOnSimpleArray2(result); + testRemoveObjectOnEmptyObject(result); + testRemoveObjectOnEmptyArray(result); + testRemoveObjectOnSimpleObject(result); + testRemoveObjectOnSimpleArray(result); + testRemoveObjectOnSimpleArray2(result); + testRemoveFromNonExistingLocationInObject(result); + testRemoveFromNonExistingLocationInArray(result); + return result; + } + + /** + * Test pointer remove operation for {@code String} to produce empty JSON + * object. + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnEmptyObject(final TestResult result) { + System.out.println(" - for String to produce empty JSON object"); + final JsonObject in = createSimpleObjectStr(); + final JsonObject check = createEmptyObject(); + simpleOperation(result, in, check, STR_PATH, null); + } + + /** + * Test pointer remove operation for {@code String} to produce empty JSON + * array. Only allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnEmptyArray(final TestResult result) { + System.out.println(" - for String to produce empty JSON array"); + final JsonArray in = createEmptyArrayWithStr(); + final JsonArray check = createEmptyArray(); + simpleOperation(result, in, check, "/0", null); + } + + /** + * Test pointer remove operation for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnSimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObjectWithStr(); + final JsonObject check = createSimpleObject(); + simpleOperation(result, in, check, STR_PATH, null); + } + + /** + * Test pointer remove operation for {@code String} on simple JSON array of + * size 2. Using index {@code 0} to remove {@code String} before another + * existing element and index {@code 1} to remove {@code String} after another + * existing element. + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnSimpleArray(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 2"); + final JsonArray inBefore = createSimpleStringArrayWithStrBefore(); + final JsonArray inAfter = createSimpleStringArrayWithStrAfter(); + final JsonArray check = createStringArray1(); + simpleOperation(result, inBefore, check, "/0", null); + simpleOperation(result, inAfter, check, "/1", null); + } + + /** + * Test pointer REMOVE for {@code String} on simple JSON array of size 5. + * Starting with an array of size 2. + * <ul> + * <li>Removing {@code String} at the end, at the middle and at the beginning + * of this array. + * <li>Removing {@code String} at the beginning, in the middle and at the end + * of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnSimpleArray2(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 5"); + final JsonArray in = createSimpleStringArray5(); + final JsonArray check = createStringArray2(); + complexOperation(result, in, check, new String[] { "/4", "/2", "/0" }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/2" }); + } + + /** + * Test pointer REMOVE operation for {@code int} to produce empty JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnEmptyObject(final TestResult result) { + System.out.println(" - for int to produce empty JSON object"); + final JsonObject in = createSimpleObjectInt(); + final JsonObject check = createEmptyObject(); + simpleOperation(result, in, check, INT_PATH, null); + } + + /** + * Test pointer REMOVE operation for {@code int} to produce empty JSON array. + * Only allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnEmptyArray(final TestResult result) { + System.out.println(" - for int to produce empty JSON array"); + final JsonArray in = createEmptyArrayWithInt(); + final JsonArray check = createEmptyArray(); + simpleOperation(result, in, check, "/0", null); + } + + /** + * Test pointer REMOVE operation for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnSimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObjectWithInt(); + final JsonObject check = createSimpleObject(); + simpleOperation(result, in, check, INT_PATH, null); + } + + /** + * Test pointer REMOVE operation for {@code int} on simple JSON array of size + * 2. Using index {@code 0} to remove {@code int} before another existing + * element and index {@code 1} to remove {@code int} after another existing + * element. + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnSimpleArray(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 2"); + final JsonArray inBefore = createSimpleIntArrayWithIntBefore(); + final JsonArray inAfter = createSimpleIntArrayWithIntAfter(); + final JsonArray check = createIntArray1(); + simpleOperation(result, inBefore, check, "/0", null); + simpleOperation(result, inAfter, check, "/1", null); + } + + /** + * Test pointer REMOVE for {@code int} on simple JSON array of size 5. + * Starting with an array of size 5. + * <ul> + * <li>Removing {@code int} at the end, at the middle and at the beginning of + * this array. + * <li>Removing {@code int} at the beginning, in the middle and at the end of + * this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnSimpleArray2(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 5"); + final JsonArray in = createSimpleIntArray5(); + final JsonArray check = createIntArray2(); + complexOperation(result, in, check, new String[] { "/4", "/2", "/0" }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/2" }); + } + + /** + * Test pointer REMOVE operation for {@code boolean} to produce empty JSON + * object. + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnEmptyObject(final TestResult result) { + System.out.println(" - for boolean to produce empty JSON object"); + final JsonObject in = createSimpleObjectBool(); + final JsonObject check = createEmptyObject(); + simpleOperation(result, in, check, BOOL_PATH, null); + } + + /** + * Test pointer REMOVE operation for {@code boolean} to produce empty JSON + * array. Only allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnEmptyArray(final TestResult result) { + System.out.println(" - for boolean to produce empty JSON array"); + final JsonArray in = createEmptyArrayWithBool(); + final JsonArray check = createEmptyArray(); + simpleOperation(result, in, check, "/0", null); + } + + /** + * Test pointer REMOVE operation for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnSimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObjectWithBool(); + final JsonObject check = createSimpleObject(); + simpleOperation(result, in, check, BOOL_PATH, null); + } + + /** + * Test pointer REMOVE operation for {@code boolean} on simple JSON array of + * size 2. Using index {@code 0} to remove {@code boolean} before another + * existing element and index {@code 1} to remove {@code boolean} after + * another existing element. + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnSimpleArray(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 2"); + final JsonArray inBefore = createSimpleBoolArrayWithBoolBefore(); + final JsonArray inAfter = createSimpleBoolArrayWithBoolAfter(); + final JsonArray check = createBoolArray1(); + simpleOperation(result, inBefore, check, "/0", null); + simpleOperation(result, inAfter, check, "/1", null); + } + + /** + * Test pointer REMOVE for {@code boolean} on simple JSON array of size 5. + * Starting with an array of size 5. + * <ul> + * <li>Removing {@code boolean} at the end, at the middle and at the beginning + * of this array. + * <li>Removing {@code boolean} at the beginning, in the middle and at the end + * of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnSimpleArray2(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 5"); + final JsonArray in = createSimpleBoolArray5(); + final JsonArray check = createBoolArray2(); + complexOperation(result, in, check, new String[] { "/4", "/2", "/0" }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/2" }); + } + + /** + * Test pointer REMOVE operation for {@code JsonObject} to produce empty JSON + * object. + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnEmptyObject(final TestResult result) { + System.out.println(" - for JsonObject to produce empty JSON object"); + final JsonObject in = createSimpleObjectObject(); + final JsonObject check = createEmptyObject(); + simpleOperation(result, in, check, OBJ_PATH, null); + } + + /** + * Test pointer REMOVE operation for {@code JsonObject} to produce empty JSON + * array. Only allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnEmptyArray(final TestResult result) { + System.out.println(" - for JsonObject to produce empty JSON array"); + final JsonArray in = createEmptyArrayWithObject(); + final JsonArray check = createEmptyArray(); + simpleOperation(result, in, check, "/0", null); + } + + /** + * Test pointer REMOVE operation for {@code JsonObject} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnSimpleObject(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON object"); + final JsonObject in = createCompoundObjectWithObject(); + final JsonObject check = createCompoundObject(); + simpleOperation(result, in, check, OBJ_PATH, null); + } + + /** + * Test pointer REMOVE operation for {@code JsonObject} on simple JSON array + * of size 2. Using index {@code 0} to remove {@code JsonObject} before + * another existing element and index {@code 1} to remove {@code JsonObject} + * after another existing element. + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnSimpleArray(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 2"); + final JsonArray inBefore = createSimpleObjectArrayWithObjectBefore(); + final JsonArray inAfter = createSimpleObjectArrayWithObjectAfter(); + final JsonArray check = createObjectArray1(); + simpleOperation(result, inBefore, check, "/0", null); + simpleOperation(result, inAfter, check, "/1", null); + } + + /** + * Test pointer REMOVE for {@code JsonObject} on simple JSON array of size 5. + * Starting with an array of size 5. + * <ul> + * <li>Removing {@code JsonObject} at the end, at the middle and at the + * beginning of this array. + * <li>Removing {@code JsonObject} at the beginning, in the middle and at the + * end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnSimpleArray2(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 5"); + final JsonArray in = createSimpleObjectArray5(); + final JsonArray check = createObjectArray2(); + complexOperation(result, in, check, new String[] { "/4", "/2", "/0" }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/2" }); + } + + // Tests based on RFC 6902 definitions and examples. + + /** + * Test pointer REMOVE for non existing location in object. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.2">RFC 6902: + * 4.2. remove</a>} defines:<br> + * The target location MUST exist for the operation to be successful. + */ + private void testRemoveFromNonExistingLocationInObject( + final TestResult result) { + System.out.println(" - for non existing location in JsonObject"); + final JsonObject[] objsIn = new JsonObject[] { createEmptyObject(), + createSimpleObject(), createCompoundObject() }; + final String[] paths = new String[] { STR_PATH, INT_PATH, BOOL_PATH, + OBJ_PATH }; + // Go trough all objects + for (int i = 0; i < objsIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + simpleOperationFail(result, objsIn[i], paths[j], null); + } + } + } + + /** + * Test pointer REMOVE for non existing location in array. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.2">RFC 6902: + * 4.2. remove</a>} defines:<br> + * The target location MUST exist for the operation to be successful. + */ + private void testRemoveFromNonExistingLocationInArray( + final TestResult result) { + System.out.println(" - for non existing location in JsonArray"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray1(), createIntArray2(), createSimpleBoolArray5(), + createObjectArray2() + + }; + final String[] paths = new String[] { "/", "/-1", "/-", "/5", "/0a", "/42", + STR_PATH + "/0" }; + // Go trough all arrays + for (int i = 0; i < arraysIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + simpleOperationFail(result, arraysIn[i], paths[j], null); + } + } + } + + /** + * Tested operation name {@code "REMOVE"}. + * + * @return Operation name to be used in logs. + */ + @Override + protected String operationName() { + return OPERATION; + } + + /** + * Create and initialize patch builder to contain REMOVE operation to be + * applied. + * + * @param path + * JSON path of value to removed. + * @param value + * Not used for REMOVE operation. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder createOperationBuilder(final String path, + final Object value) { + return Json.createPatchBuilder().remove(path); + } + + /** + * Update patch builder to contain next REMOVE operation to be applied. + * + * @param builder + * JSON patch builder to update. + * @param path + * JSON path of value to removed. + * @param value + * Not used for REMOVE operation. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder updateOperationBuilder( + final JsonPatchBuilder builder, final String path, final Object value) { + return builder.remove(path); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationReplace.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationReplace.java new file mode 100644 index 0000000..66190c5 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationReplace.java
@@ -0,0 +1,396 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.JsonValueType; +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * RFC 6902: JavaScript Object Notation (JSON) Patch compatibility tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>}. + * <p> + * Implements + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.3">RFC 6902: + * 4.3. replace</a>} tests. + */ +public class PatchOperationReplace extends CommonOperation { + + /** Tested operation name. */ + private final String OPERATION = "REPLACE"; + + /** + * Creates an instance of RFC 6902 replace operation test. + */ + PatchOperationReplace() { + super(); + } + + /** + * Test RFC 6902 replace operation. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult("RFC 6902 replace operation"); + System.out.println("Testing RFC 6902 replace operation:"); + testReplaceStringOnSimpleObject(result); + testReplaceStringOnSimpleArray(result); + testReplaceStringOnSimpleArray2(result); + testReplaceIntOnSimpleObject(result); + testReplaceIntOnSimpleArray(result); + testReplaceIntOnSimpleArray2(result); + testReplaceBoolOnSimpleObject(result); + testReplaceBoolOnSimpleArray(result); + testReplaceBoolOnSimpleArray2(result); + testReplaceObjectOnCompoundObject(result); + testReplaceObjectOnSimpleArray(result); + testReplaceObjectOnSimpleArray2(result); + testReplaceOfNonExistingLocationInObject(result); + testReplaceOfNonExistingLocationInArray(result); + return result; + } + + /** + * Test pointer replace operation for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testReplaceStringOnSimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObjectStr(); + final JsonObject check = createSimpleObjectReplaceStr(); + simpleOperation(result, in, check, STR_PATH, STR_VALUE2); + } + + /** + * Test pointer replace operation for {@code String} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testReplaceStringOnSimpleArray(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 1"); + final JsonArray in = createStringArray1(); + final JsonArray check = createSimpleStringArrayReplaceStr(); + simpleOperation(result, in, check, "/0", STR_VALUE); + } + + /** + * Test pointer replace operation for {@code String} on simple JSON array of + * size 5. Starting with an array of size 5. + * <ul> + * <li>Replacing {@code String} items from the end to the beginning of this + * array. + * <li>Replacing {@code String} from the beginning to the end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testReplaceStringOnSimpleArray2(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 5"); + final JsonArray in = createSimpleStringArray5(); + final JsonArray check = createSimpleStringArray5R(); + complexOperation(result, in, check, new String[] { "/4", "/3", "/1", "/0" }, + new String[] { STR_VALUE_1, STR_VALUE_2, STR_VALUE_4, STR_VALUE_5 }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/3", "/4" }, + new String[] { STR_VALUE_5, STR_VALUE_4, STR_VALUE_2, STR_VALUE_1 }); + } + + /** + * Test pointer replace operation for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testReplaceIntOnSimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObjectInt(); + final JsonObject check = createSimpleObjectReplaceInt(); + simpleOperation(result, in, check, INT_PATH, INT_VALUE2); + } + + /** + * Test pointer replace operation for {@code int} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testReplaceIntOnSimpleArray(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 1"); + final JsonArray in = createIntArray1(); + final JsonArray check = createSimpleIntArrayReplaceInt(); + simpleOperation(result, in, check, "/0", INT_VALUE); + } + + /** + * Test pointer replace operation for {@code int} on simple JSON array of size + * 5. Starting with an array of size 5. + * <ul> + * <li>Replacing {@code int} items from the end to the beginning of this + * array. + * <li>Replacing {@code int} from the beginning to the end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testReplaceIntOnSimpleArray2(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 5"); + final JsonArray in = createSimpleIntArray5(); + final JsonArray check = createSimpleIntArray5R(); + complexOperation(result, in, check, new String[] { "/4", "/3", "/1", "/0" }, + new Integer[] { INT_VALUE_1, INT_VALUE_2, INT_VALUE_4, INT_VALUE_5 }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/3", "/4" }, + new Integer[] { INT_VALUE_5, INT_VALUE_4, INT_VALUE_2, INT_VALUE_1 }); + } + + /** + * Test pointer replace operation for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testReplaceBoolOnSimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObjectBool(); + final JsonObject check = createSimpleObjectReplaceBool(); + simpleOperation(result, in, check, BOOL_PATH, BOOL_VALUE2); + } + + /** + * Test pointer replace operation for {@code boolean} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testReplaceBoolOnSimpleArray(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 1"); + final JsonArray in = createBoolArray1(); + final JsonArray check = createSimpleBoolArrayReplaceBool(); + simpleOperation(result, in, check, "/0", BOOL_FALSE); + } + + /** + * Test pointer replace operation for {@code boolean} on simple JSON array of + * size 5. Starting with an array of size 5. + * <ul> + * <li>Replacing {@code boolean} items from the end to the beginning of this + * array. + * <li>Replacing {@code boolean} from the beginning to the end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testReplaceBoolOnSimpleArray2(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 5"); + final JsonArray in = createSimpleBoolArray5(); + final JsonArray check = createSimpleBoolArray5R(); + complexOperation(result, in, check, new String[] { "/4", "/3", "/1", "/0" }, + new Boolean[] { BOOL_FALSE, BOOL_TRUE, BOOL_FALSE, BOOL_TRUE }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/3", "/4" }, + new Boolean[] { BOOL_TRUE, BOOL_FALSE, BOOL_TRUE, BOOL_FALSE }); + } + + /** + * Test pointer replace operation for {@code JsonObject} on compound JSON + * object. + * + * @param result + * Tests result record. + */ + private void testReplaceObjectOnCompoundObject(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON object"); + final JsonObject in = createCompoundObjectWithObject(); + final JsonObject check = createCompoundObjectReplaceObject(); + simpleOperation(result, in, check, OBJ_PATH, OBJ_VALUE2); + } + + /** + * Test pointer replace operation for {@code JsonObject} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testReplaceObjectOnSimpleArray(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 1"); + final JsonArray in = createObjectArray1(); + final JsonArray check = createSimpleObjectArrayReplaceObject(); + simpleOperation(result, in, check, "/0", OBJ_VALUE); + } + + /** + * Test pointer replace operation for {@code JsonObject} on simple JSON array + * of size 5. Starting with an array of size 5. + * <ul> + * <li>Replacing {@code JsonObject} items from the end to the beginning of + * this array. + * <li>Replacing {@code JsonObject} from the beginning to the end of this + * array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testReplaceObjectOnSimpleArray2(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 5"); + final JsonArray in = createSimpleObjectArray5(); + final JsonArray check = createSimpleObjectArray5R(); + complexOperation(result, in, check, new String[] { "/4", "/3", "/1", "/0" }, + new JsonObject[] { OBJ_VALUE_1, OBJ_VALUE_2, OBJ_VALUE_4, + OBJ_VALUE_5 }); + complexOperation(result, in, check, new String[] { "/0", "/1", "/3", "/4" }, + new JsonObject[] { OBJ_VALUE_5, OBJ_VALUE_4, OBJ_VALUE_2, + OBJ_VALUE_1 }); + } + + // Tests based on RFC 6902 definitions and examples. + + /** + * Test pointer replace for non existing location in object. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.3">RFC 6902: + * 4.3. replace</a>} defines:<br> + * The target location MUST exist for the operation to be successful. + */ + private void testReplaceOfNonExistingLocationInObject( + final TestResult result) { + System.out.println(" - for non existing location in JsonObject"); + final JsonObject[] objsIn = new JsonObject[] { createEmptyObject(), + createSimpleObject(), createCompoundObject() }; + final String[] paths = new String[] { STR_PATH, INT_PATH, BOOL_PATH, + OBJ_PATH }; + final Object[] values = new Object[] { STR_VALUE, INT_VALUE, BOOL_VALUE, + OBJ_VALUE }; + // Go trough all objects + for (int i = 0; i < objsIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + simpleOperationFail(result, objsIn[i], paths[j], values[i]); + } + } + } + + /** + * Test pointer replace for non existing location in array. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.3">RFC 6902: + * 4.3. replace</a>} defines:<br> + * The target location MUST exist for the operation to be successful. + */ + private void testReplaceOfNonExistingLocationInArray( + final TestResult result) { + System.out.println(" - for non existing location in JsonArray"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray1(), createIntArray2(), createSimpleBoolArray5(), + createObjectArray2() }; + final String[] paths = new String[] { "/", "/-1", "/-", "/5", "/0a", "/42", + STR_PATH + "/0" }; + final Object[] values = new Object[] { STR_VALUE, STR_VALUE, INT_VALUE, + BOOL_VALUE, OBJ_VALUE }; + // Go trough all arrays + for (int i = 0; i < arraysIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + simpleOperationFail(result, arraysIn[i], paths[j], values[i]); + } + } + } + + /** + * Tested operation name {@code "MOVE"}. + * + * @return Operation name to be used in logs. + */ + @Override + protected String operationName() { + return OPERATION; + } + + /** + * Create and initialize patch builder to contain REPLACE operation to be + * applied. + * + * @param path + * JSON path of value to be replaced. + * @param value + * Value to replace previous one. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder createOperationBuilder(final String path, + final Object value) { + return builderReplace(Json.createPatchBuilder(), path, value); + } + + /** + * Update patch builder to contain next REPLACE operation to be applied. + * + * @param builder + * JSON patch builder to update. + * @param path + * JSON path of value to be replaced. + * @param value + * Value to replace previous one. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder updateOperationBuilder( + final JsonPatchBuilder builder, final String path, final Object value) { + return builderReplace(builder, path, value); + } + + /** + * Add REPLACE {@code value} at {@code path} operation to provided JSON patch + * builder. + * + * @param builder + * Target JSON patch builder. + * @param path + * JSON path of value to be replaced. + * @param value + * Value to be replaced at given JSON path. + * @return JSON patch builder containing new {@code value} at {@code path} + * replaced. + */ + @SuppressWarnings("UnnecessaryUnboxing") + private static JsonPatchBuilder builderReplace(final JsonPatchBuilder builder, + final String path, final Object value) { + switch (JsonValueType.getType(value.getClass())) { + case String: + return builder.replace(path, (String) value); + case Integer: + return builder.replace(path, ((Integer) value).intValue()); + case Boolean: + return builder.replace(path, ((Boolean) value).booleanValue()); + case JsonValue: + return builder.replace(path, (JsonValue) value); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationTest.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationTest.java new file mode 100644 index 0000000..14ac33b --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchOperationTest.java
@@ -0,0 +1,413 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.JsonValueType; +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonPatchBuilder; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * RFC 6902: JavaScript Object Notation (JSON) Patch compatibility tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>}. + * <p> + * Implements + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.6">RFC 6902: + * 4.6. test</a>} tests. + */ +public class PatchOperationTest extends CommonOperation { + + /** Tested operation name. */ + private final String OPERATION = "TEST"; + + /** + * Creates an instance of RFC 6902 replace operation test. + */ + PatchOperationTest() { + super(); + } + + /** + * Test RFC 6902 MOVE operation. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult("RFC 6902 test operation"); + System.out.println("Testing RFC 6902 test operation:"); + testOnEmptyObject(result); + testOnEmptyArray(result); + testOnSimpleObject(result); + testOnSimpleStringArray(result); + testOnSimpleIntArray(result); + testOnSimpleBoolArray(result); + testOnSimpleObjectArray(result); + return result; + } + + /** + * Test RFC 6902 TEST operation on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testOnEmptyObject(final TestResult result) { + System.out.println(" - on empty JSON object"); + final JsonObject in = createEmptyObject(); + final String[] paths = new String[] { STR_PATH, INT_PATH, BOOL_PATH, + OBJ_PATH }; + final Object[] values = new Object[] { STR_VALUE, INT_VALUE, BOOL_VALUE, + OBJ_VALUE }; + // Go trough all values. + for (int i = 0; i < values.length; i++) { + // Go trough all paths. + for (int j = 0; j < paths.length; j++) { + // Everything shall fail on empty object. + simpleOperationFail(result, in, paths[j], values[i]); + } + } + // Whole document should pass on itself. + simpleOperation(result, in, null, "", in); + } + + /** + * Test RFC 6902 TEST operation on empty JSON array. + * + * @param result + * Tests result record. + */ + private void testOnEmptyArray(final TestResult result) { + System.out.println(" - on empty JSON array"); + final JsonArray in = createEmptyArray(); + final String[] paths = new String[] { "/-1", "/0", "/1", "/2", "/3", "/4", + "/5", "/-" }; + final Object[] values = new Object[] { STR_VALUE, INT_VALUE, BOOL_VALUE, + OBJ_VALUE }; + // Go trough all values. + for (int i = 0; i < values.length; i++) { + // Go trough all paths. + for (int j = 0; j < paths.length; j++) { + // Everything shall fail on empty object. + simpleOperationFail(result, in, paths[j], values[i]); + } + } + // Whole document should pass on itself. + simpleOperation(result, in, null, "", in); + } + + /** + * Test RFC 6902 TEST on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testOnSimpleObject(final TestResult result) { + System.out.println(" - on simple JSON object"); + final JsonObject[] in = new JsonObject[] { createSimpleObjectStr(), + createSimpleObjectInt(), createSimpleObjectBool(), + createSimpleObjectObject() }; + final String[] paths = new String[] { STR_PATH, INT_PATH, BOOL_PATH, + OBJ_PATH }; + final Object[] values = new Object[] { STR_VALUE, INT_VALUE, BOOL_VALUE, + OBJ_VALUE }; + // go trough all source objects. + for (int o = 0; o < in.length; o++) { + // Go trough all values. + for (int i = 0; i < values.length; i++) { + // Go trough all paths. + for (int j = 0; j < paths.length; j++) { + if (o == i && o == j) { + // TEST must pass for matching JsonObject, path and value + simpleOperation(result, in[o], null, paths[j], values[i]); + } else { + // TEST must fail for non matching JsonObject, path and value + simpleOperationFail(result, in[o], paths[j], values[i]); + } + } + } + // Whole document should pass on itself. + simpleOperation(result, in[o], null, "", in[o]); + } + } + + /** + * Test RFC 6902 TEST on simple JSON array of {@code String}. + * + * @param result + * Tests result record. + */ + private void testOnSimpleStringArray(final TestResult result) { + System.out.println(" - on simple JSON String array of size 5"); + final JsonArray in = createSimpleStringArray5(); + final String[] indexes = new String[] { "/-1", "/-", STR_PATH }; + final String[] values = new String[] { STR_VALUE_1, STR_VALUE_2, + STR_VALUE_3, STR_VALUE_4, STR_VALUE_5 }; + // Go trough all array indexes. + for (int i = 0; i <= 5; i++) { + final String path = arrayPtr("/", i); + // Go trough all values. + for (int v = 0; v < values.length; v++) { + if (i == v) { + // TEST must pass for matching index and value. + simpleOperation(result, in, null, path, values[v]); + } else { + // TEST must fail for non matching index and value. + simpleOperationFail(result, in, path, values[v]); + } + } + } + // Go trough all invalid indexes + for (int i = 0; i < indexes.length; i++) { + // Go trough all values. + for (int v = 0; v < values.length; v++) { + // TEST must fail for non matching index and value. + simpleOperationFail(result, in, indexes[i], values[v]); + } + } + // Whole document should pass on itself. + simpleOperation(result, in, null, "", in); + } + + /** + * Test RFC 6902 TEST on simple JSON array of {@code int}. + * + * @param result + * Tests result record. + */ + private void testOnSimpleIntArray(final TestResult result) { + System.out.println(" - on simple JSON int array of size 5"); + final JsonArray in = createSimpleIntArray5(); + final String[] indexes = new String[] { "/-1", "/-", INT_PATH }; + final int[] values = new int[] { INT_VALUE_1, INT_VALUE_2, INT_VALUE_3, + INT_VALUE_4, INT_VALUE_5 }; + // Go trough all array indexes. + for (int i = 0; i <= 5; i++) { + final String path = arrayPtr("/", i); + // Go trough all values. + for (int v = 0; v < values.length; v++) { + if (i == v) { + // TEST must pass for matching index and value. + simpleOperation(result, in, null, path, values[v]); + } else { + // TEST must fail for non matching index and value. + simpleOperationFail(result, in, path, values[v]); + } + } + } + // Go trough all invalid indexes + for (int i = 0; i < indexes.length; i++) { + // Go trough all values. + for (int v = 0; v < values.length; v++) { + // TEST must fail for non matching index and value. + simpleOperationFail(result, in, indexes[i], values[v]); + } + } + // Whole document should pass on itself. + simpleOperation(result, in, null, "", in); + } + + /** + * Test RFC 6902 TEST on simple JSON array of {@code boolean}. + * + * @param result + * Tests result record. + */ + private void testOnSimpleBoolArray(final TestResult result) { + System.out.println(" - on simple JSON boolean array of size 2"); + final JsonArray in = createBoolArray2(); + final String[] indexes = new String[] { "/-1", "/-", BOOL_PATH }; + final boolean[] values = new boolean[] { BOOL_TRUE, BOOL_FALSE }; + // Go trough all array indexes. + for (int i = 0; i <= 2; i++) { + final String path = arrayPtr("/", i); + // Go trough all values. + for (int v = 0; v < values.length; v++) { + if (i == v) { + // TEST must pass for matching index and value. + simpleOperation(result, in, null, path, values[v]); + } else { + // TEST must fail for non matching index and value. + simpleOperationFail(result, in, path, values[v]); + } + } + } + // Go trough all invalid indexes + for (int i = 0; i < indexes.length; i++) { + // Go trough all values. + for (int v = 0; v < values.length; v++) { + // TEST must fail for non matching index and value. + simpleOperationFail(result, in, indexes[i], values[v]); + } + } + // Whole document should pass on itself. + simpleOperation(result, in, null, "", in); + } + + /** + * Test RFC 6902 TEST on simple JSON array of {@code JsonObject}. + * + * @param result + * Tests result record. + */ + private void testOnSimpleObjectArray(final TestResult result) { + System.out.println(" - on simple JSON JsonObject array of size 5"); + final JsonArray in = createSimpleObjectArray5(); + final String[] indexes = new String[] { "/-1", "/-", OBJ_PATH }; + final JsonObject[] values = new JsonObject[] { OBJ_VALUE_1, OBJ_VALUE_2, + OBJ_VALUE_3, OBJ_VALUE_4, OBJ_VALUE_5 }; + // Go trough all array indexes. + for (int i = 0; i <= 5; i++) { + final String path = arrayPtr("/", i); + // Go trough all values. + for (int v = 0; v < values.length; v++) { + if (i == v) { + // TEST must pass for matching index and value. + simpleOperation(result, in, null, path, values[v]); + } else { + // TEST must fail for non matching index and value. + simpleOperationFail(result, in, path, values[v]); + } + } + } + // Go trough all invalid indexes + for (int i = 0; i < indexes.length; i++) { + // Go trough all values. + for (int v = 0; v < values.length; v++) { + // TEST must fail for non matching index and value. + simpleOperationFail(result, in, indexes[i], values[v]); + } + } + // Whole document should pass on itself. + simpleOperation(result, in, null, "", in); + } + + /** + * Build JSON array pointer for given prefix and index. + * + * @param prefix + * JSON array pointer prefix. + * @param index + * JSON array pointer index. + * @return JSON array pointer. + */ + private static String arrayPtr(final String prefix, final int index) { + final int prefixLen = prefix != null ? prefix.length() : 0; + final String indexStr = Integer.toString(index); + final StringBuilder sb = new StringBuilder(prefixLen + indexStr.length()); + if (prefixLen > 0) { + sb.append(prefix); + } + sb.append(indexStr); + return sb.toString(); + } + + /** + * Tested operation name {@code "TEST"}. + * + * @return Operation name to be used in logs. + */ + @Override + protected String operationName() { + return OPERATION; + } + + /** + * Create and initialize patch builder to contain TEST operation to be + * applied. + * + * @param path + * JSON path of value to be tested. + * @param value + * Value to be compared against value on specified path. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder createOperationBuilder(final String path, + final Object value) { + return builderTest(Json.createPatchBuilder(), path, value); + } + + /** + * Update patch builder to contain next TEST operation to be applied. + * + * @param builder + * JSON patch builder to update. + * @param path + * JSON path of value to be tested. + * @param value + * Value to be compared against value on specified path. + * @return Patch builder containing operation to be applied. + */ + @Override + protected JsonPatchBuilder updateOperationBuilder( + final JsonPatchBuilder builder, final String path, final Object value) { + return builderTest(builder, path, value); + } + + /** + * Add TEST {@code value} at {@code path} operation to provided JSON patch + * builder. + * + * @param builder + * Target JSON patch builder. + * @param path + * JSON path of value to be tested. + * @param value + * Value to be compared against value on specified path. + * @return JSON patch builder containing new TEST operation. + */ + @SuppressWarnings("UnnecessaryUnboxing") + private static JsonPatchBuilder builderTest(final JsonPatchBuilder builder, + final String path, final Object value) { + switch (JsonValueType.getType(value.getClass())) { + case String: + return builder.test(path, (String) value); + case Integer: + return builder.test(path, ((Integer) value).intValue()); + case Boolean: + return builder.test(path, ((Boolean) value).booleanValue()); + case JsonValue: + return builder.test(path, (JsonValue) value); + default: + throw new IllegalArgumentException( + "Value does not match known JSON value type"); + } + } + + /** + * Operation result check. + * + * @param check + * Expected modified JSON value. + * @param out + * Operation output. + * @return Value of {@code true} if operation passed or {@code false} + * otherwise. + */ + @Override + protected boolean operationFailed(final JsonValue check, + final JsonValue out) { + return out == null; + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchTests.java new file mode 100644 index 0000000..1c66c45 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/patchtests/PatchTests.java
@@ -0,0 +1,206 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.patchtests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.lib.harness.Fault; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +// $Id$ +/* + * RFC 6902: JavaScript Object Notation (JSON) Patch compatibility tests.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>}. + */ +@RunWith(Arquillian.class) +public class PatchTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, PatchTests.class.getPackage().getName()); + } + /** + * Test {@link JsonPatch} factory methods added in JSON-P 1.1. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonCreatePatch11Test + * + * @assertion_ids: JSONP:JAVADOC:574; JSONP:JAVADOC:579; JSONP:JAVADOC:581; + * JSONP:JAVADOC:653; JSONP:JAVADOC:658; JSONP:JAVADOC:660; + * JSONP:JAVADOC:620; JSONP:JAVADOC:621; + * + * @test_Strategy: Tests JsonPatch API factory methods added in JSON-P 1.1. + */ + @Test + public void jsonCreatePatch11Test() throws Fault { + PatchCreate createTest = new PatchCreate(); + final TestResult result = createTest.test(); + result.eval(); + } + + /** + * Test {@code JsonPatch.Operation} enumeration added in JSON-P 1.1. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonJsonPatchOperation11Test + * + * @assertion_ids: JSONP:JAVADOC:622; JSONP:JAVADOC:623; JSONP:JAVADOC:624; + * JSONP:JAVADOC:625; + * + * @test_Strategy: Tests JsonPatch.Operation enumeration added in JSON-P 1.1. + */ + @Test + public void jsonJsonPatchOperation11Test() throws Fault { + PatchOperationEnum enumTest = new PatchOperationEnum(); + final TestResult result = enumTest.test(); + result.eval(); + } + + /** + * Test JSONP API response on add operation.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC 6902: + * 4.1. add</a>}. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPatchAddTest + * @assertion_ids: JSONP:JAVADOC:626; JSONP:JAVADOC:627; JSONP:JAVADOC:628; + * JSONP:JAVADOC:629; JSONP:JAVADOC:580; JSONP:JAVADOC:659; + * JSONP:JAVADOC:620; JSONP:JAVADOC:630; + * @test_Strategy: Test API response on various usages of add operation. + */ + @Test + public void jsonPatchAddTest() throws Fault { + PatchOperationAdd addTest = new PatchOperationAdd(); + final TestResult result = addTest.test(); + result.eval(); + } + + /** + * Test JSONP API response on remove operation.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.2">RFC 6902: + * 4.2. remove</a>}. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPatchRemoveTest + * @assertion_ids: JSONP:JAVADOC:633; JSONP:JAVADOC:580; JSONP:JAVADOC:659; + * JSONP:JAVADOC:620; JSONP:JAVADOC:630; + * @test_Strategy: Test API response on various usages of remove operation. + */ + @Test + public void jsonPatchRemoveTest() throws Fault { + PatchOperationRemove removeTest = new PatchOperationRemove(); + final TestResult result = removeTest.test(); + result.eval(); + } + + /** + * Test JSONP API response on replace operation.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.3">RFC 6902: + * 4.3. replace</a>}. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPatchReplaceTest + * @assertion_ids: JSONP:JAVADOC:634; JSONP:JAVADOC:635; JSONP:JAVADOC:636; + * JSONP:JAVADOC:637; JSONP:JAVADOC:580; JSONP:JAVADOC:659; + * JSONP:JAVADOC:620; JSONP:JAVADOC:630; + * @test_Strategy: Test API response on various usages of replace operation. + */ + @Test + public void jsonPatchReplaceTest() throws Fault { + PatchOperationReplace replaceTest = new PatchOperationReplace(); + final TestResult result = replaceTest.test(); + result.eval(); + } + + /** + * Test JSONP API response on move operation.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.4">RFC 6902: + * 4.4. move</a>}. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPatchMoveTest + * @assertion_ids: JSONP:JAVADOC:632; JSONP:JAVADOC:580; JSONP:JAVADOC:659; + * JSONP:JAVADOC:620; JSONP:JAVADOC:630; + * @test_Strategy: Test API response on various usages of move operation. + */ + @Test + public void jsonPatchMoveTest() throws Fault { + PatchOperationMove moveTest = new PatchOperationMove(); + final TestResult result = moveTest.test(); + result.eval(); + } + + /** + * Test JSONP API response on copy operation.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.5">RFC 6902: + * 4.5. copy</a>}. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPatchCopyTest + * @assertion_ids: JSONP:JAVADOC:631; JSONP:JAVADOC:580; JSONP:JAVADOC:659; + * JSONP:JAVADOC:620; JSONP:JAVADOC:630; + * @test_Strategy: Test API response on various usages of copy operation. + */ + @Test + public void jsonPatchCopyTest() throws Fault { + PatchOperationCopy copyTest = new PatchOperationCopy(); + final TestResult result = copyTest.test(); + result.eval(); + } + + /** + * Test JSONP API response on test operation.<br> + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.6">RFC 6902: + * 4.6. test</a>}. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPatchTestTest + * @assertion_ids: JSONP:JAVADOC:638; JSONP:JAVADOC:639; JSONP:JAVADOC:640; + * JSONP:JAVADOC:641; JSONP:JAVADOC:580; JSONP:JAVADOC:659; + * JSONP:JAVADOC:620; JSONP:JAVADOC:630; + * @test_Strategy: Test API response on various usages of test operation. + */ + @Test + public void jsonPatchTestTest() throws Fault { + PatchOperationTest testTest = new PatchOperationTest(); + final TestResult result = testTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerAdd.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerAdd.java new file mode 100644 index 0000000..7b0d9d4 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerAdd.java
@@ -0,0 +1,695 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.pointertests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; +import jakarta.json.JsonStructure; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * {@see <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>}: pointer + * usage for {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>} + * add operation tests.<br> + */ +public class PointerAdd { + + /** + * Creates an instance of RFC 6901 pointer instance usage for RFC 6902 add + * operation tests. + */ + PointerAdd() { + super(); + } + + /** + * Test RFC 6901 pointer instance usage for RFC 6902 add operation. Suite + * entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "RFC 6901 pointer usage for RFC 6902 add operation"); + System.out.println("Testing RFC 6901 pointer usage for RFC 6902 add operation"); + testAddStringOnEmptyObject(result); + testAddStringOnEmptyArray(result); + testAddStringOnSimpleObject(result); + testAddStringOnSimpleArray(result); + testAddStringOnSimpleArray2(result); + testAddIntOnEmptyObject(result); + testAddIntOnEmptyArray(result); + testAddIntOnSimpleObject(result); + testAddIntOnSimpleArray(result); + testAddIntOnSimpleArray2(result); + testAddBoolOnEmptyObject(result); + testAddBoolOnEmptyArray(result); + testAddBoolOnSimpleObject(result); + testAddBoolOnSimpleArray(result); + testAddBoolOnSimpleArray2(result); + testAddObjectOnEmptyObject(result); + testAddObjectOnEmptyArray(result); + testAddObjectOnSimpleObject(result); + testAddObjectOnSimpleArray(result); + testAddObjectOnSimpleArray2(result); + testAddArrayToReplaceObject(result); + testAddArrayToReplaceDocument(result); + testAddStringArrayToStringArray(result); + testAddStringToNonExistingObject(result); + return result; + } + + /** + * Test pointer ADD operation for {@code String} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testAddStringOnEmptyObject(final TestResult result) { + System.out.println(" - for String on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject check = createSimpleObjectStr(); + final JsonPointer ptr = Json.createPointer(STR_PATH); + final JsonObject out = ptr.add(in, Json.createValue(STR_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + STR_PATH + "\" ADD \"" + + STR_VALUE + "\" failed on empty JSON object"); + } + } + + /** + * Test pointer ADD operation for {@code String} on empty JSON array. Only + * allowed index for empty array is {@code 0} and {@code -}. + * + * @param result + * Tests result record. + */ + private void testAddStringOnEmptyArray(final TestResult result) { + System.out.println(" - for String on empty JSON array"); + final JsonArray in = createEmptyArray(); + final JsonArray check = createEmptyArrayWithStr(); + final JsonPointer[] ptrs = new JsonPointer[] { Json.createPointer("/0"), + Json.createPointer("/-") }; + for (final JsonPointer ptr : ptrs) { + final JsonArray out = ptr.add(in, Json.createValue(STR_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + ptr + "\" ADD \"" + + STR_VALUE + "\" failed on empty JSON array"); + } + } + } + + /** + * Test pointer ADD operation for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testAddStringOnSimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject check = createSimpleObjectWithStr(); + final JsonPointer ptr = Json.createPointer(STR_PATH); + final JsonObject out = ptr.add(in, Json.createValue(STR_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + STR_PATH + "\" ADD \"" + + STR_VALUE + "\" failed on simple JSON object"); + } + } + + /** + * Test pointer ADD operation for {@code String} on simple JSON array of size + * 1. Using index {@code 0} to add {@code String} before already existing + * element and indexes {@code 1} and {@code -} to add {@code String} after + * already existing element. + * + * @param result + * Tests result record. + */ + private void testAddStringOnSimpleArray(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 1"); + final JsonArray in = createStringArray1(); + final JsonArray checkBefore = createSimpleStringArrayWithStrBefore(); + final JsonArray checkAfter = createSimpleStringArrayWithStrAfter(); + final JsonPointer ptrBefore = Json.createPointer("/0"); + final JsonPointer[] ptrsAfter = new JsonPointer[] { + Json.createPointer("/1"), Json.createPointer("/-") }; + final JsonArray outBefore = ptrBefore.add(in, Json.createValue(STR_VALUE)); + if (!assertEquals(checkBefore, outBefore)) { + result.fail("Pointer ADD operation", "Pointer \"/0\" ADD \"" + STR_VALUE + + "\" failed on simple JSON array"); + } + for (final JsonPointer ptrAfter : ptrsAfter) { + final JsonArray outAfter = ptrAfter.add(in, Json.createValue(STR_VALUE)); + if (!assertEquals(checkAfter, outAfter)) { + result.fail("Pointer ADD operation", "Pointer \"/1\" ADD \"" + STR_VALUE + + "\" failed on simple JSON array"); + } + } + } + + /** + * Test pointer ADD operation for {@code String} on simple JSON array of size + * 2. Starting with an array of size 2. + * <ul> + * <li>Adding {@code String} at the end, in the middle and at the beginning of + * this array. + * <li>Adding {@code String} at the beginning, in the middle and at the end of + * this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testAddStringOnSimpleArray2(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 2"); + final JsonArray in = createStringArray2(); + final JsonArray check = createSimpleStringArray5(); + verifyAddValues(result, in, check, new String[] { "/2", "/1", "/0" }, + new String[] { STR_VALUE_5, STR_VALUE_3, STR_VALUE_1 }, + "Pointer ADD operation", + "Pointers \"/2\", \"/1\", \"/0\" ADD sequence failed on simple JSON array"); + verifyAddValues(result, in, check, new String[] { "/0", "/2", "/4" }, + new String[] { STR_VALUE_1, STR_VALUE_3, STR_VALUE_5 }, + "Pointer ADD operation", + "Pointers \"/0\", \"/2\", \"/4\" ADD sequence failed on simple JSON array"); + } + + /** + * Test pointer ADD operation for {@code int} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testAddIntOnEmptyObject(final TestResult result) { + System.out.println(" - for int on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject check = createSimpleObjectInt(); + final JsonPointer ptr = Json.createPointer(INT_PATH); + final JsonObject out = ptr.add(in, Json.createValue(INT_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + INT_PATH + "\" ADD \"" + + INT_VALUE + "\" failed on empty JSON object"); + } + } + + /** + * Test pointer ADD operation for {@code int} on empty JSON array. Only + * allowed index for empty array is {@code 0} and {@code -}. + * + * @param result + * Tests result record. + */ + private void testAddIntOnEmptyArray(final TestResult result) { + System.out.println(" - for int on empty JSON array"); + final JsonArray in = createEmptyArray(); + final JsonArray check = createEmptyArrayWithInt(); + final JsonPointer[] ptrs = new JsonPointer[] { Json.createPointer("/0"), + Json.createPointer("/-") }; + for (final JsonPointer ptr : ptrs) { + final JsonArray out = ptr.add(in, Json.createValue(INT_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + ptr + "\" ADD \"" + + INT_VALUE + "\" failed on empty JSON array"); + } + } + } + + /** + * Test pointer ADD operation for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testAddIntOnSimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject check = createSimpleObjectWithInt(); + final JsonPointer ptr = Json.createPointer(INT_PATH); + final JsonObject out = ptr.add(in, Json.createValue(INT_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + INT_PATH + "\" ADD \"" + + INT_VALUE + "\" failed on simple JSON object"); + } + } + + /** + * Test pointer ADD operation for {@code int} on simple JSON array of size 1. + * Using index {@code 0} to add {@code int} before already existing element + * and index {@code 1} and {@code -} to add {@code int} after already existing + * element. + * + * @param result + * Tests result record. + */ + private void testAddIntOnSimpleArray(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 1"); + final JsonArray in = createIntArray1(); + final JsonArray checkBefore = createSimpleIntArrayWithIntBefore(); + final JsonArray checkAfter = createSimpleIntArrayWithIntAfter(); + final JsonPointer ptrBefore = Json.createPointer("/0"); + final JsonPointer[] ptrsAfter = new JsonPointer[] { + Json.createPointer("/1"), Json.createPointer("/-") }; + final JsonArray outBefore = ptrBefore.add(in, Json.createValue(INT_VALUE)); + if (!assertEquals(checkBefore, outBefore)) { + result.fail("Pointer ADD operation", "Pointer \"/0\" ADD \"" + INT_VALUE + + "\" failed on simple JSON array"); + } + for (final JsonPointer ptrAfter : ptrsAfter) { + final JsonArray outAfter = ptrAfter.add(in, Json.createValue(INT_VALUE)); + if (!assertEquals(checkAfter, outAfter)) { + result.fail("Pointer ADD operation", "Pointer \"/1\" ADD \"" + INT_VALUE + + "\" failed on simple JSON array"); + } + } + } + + /** + * Test pointer ADD operation for {@code int} on simple JSON array of size 2. + * Starting with an array of size 2. + * <ul> + * <li>Adding {@code int} at the end, in the middle and at the beginning of + * this array. + * <li>Adding {@code int} at the beginning, in the middle and at the end of + * this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testAddIntOnSimpleArray2(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 2"); + final JsonArray in = createIntArray2(); + final JsonArray check = createSimpleIntArray5(); + verifyAddValues(result, in, check, new String[] { "/2", "/1", "/0" }, + new Integer[] { INT_VALUE_5, INT_VALUE_3, INT_VALUE_1 }, + "Pointer ADD operation", + "Pointers \"/2\", \"/1\", \"/0\" ADD sequence failed on simple JSON array"); + verifyAddValues(result, in, check, new String[] { "/0", "/2", "/4" }, + new Integer[] { INT_VALUE_1, INT_VALUE_3, INT_VALUE_5 }, + "Pointer ADD operation", + "Pointers \"/0\", \"/2\", \"/4\" ADD sequence failed on simple JSON array"); + } + + /** + * Test pointer ADD operation for {@code boolean} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testAddBoolOnEmptyObject(final TestResult result) { + System.out.println(" - for boolean on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject check = createSimpleObjectBool(); + final JsonPointer ptr = Json.createPointer(BOOL_PATH); + final JsonObject out = ptr.add(in, toJsonValue(BOOL_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + BOOL_PATH + + "\" ADD \"" + BOOL_VALUE + "\" failed on empty JSON object"); + } + } + + /** + * Test pointer ADD operation for {@code boolean} on empty JSON array. Only + * allowed index for empty array is {@code 0} and {@code -}. + * + * @param result + * Tests result record. + */ + private void testAddBoolOnEmptyArray(final TestResult result) { + System.out.println(" - for boolean on empty JSON array"); + final JsonArray in = createEmptyArray(); + final JsonArray check = createEmptyArrayWithBool(); + final JsonPointer[] ptrs = new JsonPointer[] { Json.createPointer("/0"), + Json.createPointer("/-") }; + for (final JsonPointer ptr : ptrs) { + final JsonArray out = ptr.add(in, toJsonValue(BOOL_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + ptr + "\" ADD \"" + + BOOL_VALUE + "\" failed on empty JSON array"); + } + } + } + + /** + * Test pointer ADD operation for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testAddBoolOnSimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObject(); + final JsonObject check = createSimpleObjectWithBool(); + final JsonPointer ptr = Json.createPointer(BOOL_PATH); + final JsonObject out = ptr.add(in, toJsonValue(BOOL_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + BOOL_PATH + + "\" ADD \"" + BOOL_VALUE + "\" failed on simple JSON object"); + } + } + + /** + * Test pointer ADD operation for {@code boolean} on simple JSON array of size + * 1. Using index {@code 0} to add {@code boolean} before already existing + * element and index {@code 1} and {@code -} to add {@code boolean} after + * already existing element. + * + * @param result + * Tests result record. + */ + private void testAddBoolOnSimpleArray(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 1"); + final JsonArray in = createBoolArray1(); + final JsonArray checkBefore = createSimpleBoolArrayWithBoolBefore(); + final JsonArray checkAfter = createSimpleBoolArrayWithBoolAfter(); + final JsonPointer ptrBefore = Json.createPointer("/0"); + final JsonPointer[] ptrsAfter = new JsonPointer[] { + Json.createPointer("/1"), Json.createPointer("/-") }; + final JsonArray outBefore = ptrBefore.add(in, toJsonValue(BOOL_FALSE)); + if (!assertEquals(checkBefore, outBefore)) { + result.fail("Pointer ADD operation", "Pointer \"/0\" ADD \"" + BOOL_FALSE + + "\" failed on simple JSON array"); + } + for (final JsonPointer ptrAfter : ptrsAfter) { + final JsonArray outAfter = ptrAfter.add(in, toJsonValue(BOOL_FALSE)); + if (!assertEquals(checkAfter, outAfter)) { + result.fail("Pointer ADD operation", "Pointer \"/1\" ADD \"" + + BOOL_FALSE + "\" failed on simple JSON array"); + } + } + } + + /** + * Test pointer ADD operation for {@code boolean} on simple JSON array of size + * 2. Starting with an array of size 2. + * <ul> + * <li>Adding {@code boolean} at the end, in the middle and at the beginning + * of this array. + * <li>Adding {@code boolean} at the beginning, in the middle and at the end + * of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testAddBoolOnSimpleArray2(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 2"); + final JsonArray in = createBoolArray2(); + final JsonArray check = createSimpleBoolArray5(); + verifyAddValues(result, in, check, new String[] { "/2", "/1", "/0" }, + new Boolean[] { BOOL_TRUE, BOOL_TRUE, BOOL_FALSE }, + "Pointer ADD operation", + "Pointers \"/2\", \"/1\", \"/0\" ADD sequence failed on simple JSON array"); + verifyAddValues(result, in, check, new String[] { "/0", "/2", "/4" }, + new Boolean[] { BOOL_FALSE, BOOL_TRUE, BOOL_TRUE }, + "Pointer ADD operation", + "Pointers \"/0\", \"/2\", \"/4\" ADD sequence failed on simple JSON array"); + } + + /** + * Test pointer ADD operation for {@code JsonObject} on empty JSON object. + * + * @param result + * Tests result record. + */ + private void testAddObjectOnEmptyObject(final TestResult result) { + System.out.println(" - for JsonObject on empty JSON object"); + final JsonObject in = createEmptyObject(); + final JsonObject check = createSimpleObjectObject(); + final JsonPointer ptr = Json.createPointer(OBJ_PATH); + final JsonObject out = ptr.add(in, OBJ_VALUE); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + OBJ_PATH + "\" ADD \"" + + OBJ_VALUE + "\" failed on empty JSON object"); + } + } + + /** + * Test pointer ADD operation for {@code JsonObject} on empty JSON array. Only + * allowed index for empty array is {@code 0} and {@code -}. + * + * @param result + * Tests result record. + */ + private void testAddObjectOnEmptyArray(final TestResult result) { + System.out.println(" - for JsonObject on empty JSON array"); + final JsonArray in = createEmptyArray(); + final JsonArray check = createEmptyArrayWithObject(); + final JsonPointer[] ptrs = new JsonPointer[] { Json.createPointer("/0"), + Json.createPointer("/-") }; + for (final JsonPointer ptr : ptrs) { + final JsonArray out = ptr.add(in, OBJ_VALUE); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + ptr + "\" ADD \"" + + OBJ_VALUE + "\" failed on empty JSON array"); + } + } + } + + /** + * Test pointer ADD operation for {@code JsonObject} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testAddObjectOnSimpleObject(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON object"); + final JsonObject in = createCompoundObject(); + final JsonObject check = createCompoundObjectWithObject(); + final JsonPointer ptr = Json.createPointer(OBJ_PATH); + final JsonObject out = ptr.add(in, OBJ_VALUE); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + OBJ_PATH + "\" ADD \"" + + OBJ_VALUE + "\" failed on simple JSON object"); + } + } + + /** + * Test pointer ADD operation for {@code JsonObject} on simple JSON array of + * size 1. Using index {@code 0} to add {@code JsonObject} before already + * existing element and index {@code 1} and {@code -} to add + * {@code JsonObject} after already existing element. + * + * @param result + * Tests result record. + */ + private void testAddObjectOnSimpleArray(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 1"); + final JsonArray in = createObjectArray1(); + final JsonArray checkBefore = createSimpleObjectArrayWithObjectBefore(); + final JsonArray checkAfter = createSimpleObjectArrayWithObjectAfter(); + final JsonPointer ptrBefore = Json.createPointer("/0"); + final JsonPointer[] ptrsAfter = new JsonPointer[] { + Json.createPointer("/1"), Json.createPointer("/-") }; + final JsonArray outBefore = ptrBefore.add(in, OBJ_VALUE); + if (!assertEquals(checkBefore, outBefore)) { + result.fail("Pointer ADD operation", "Pointer \"/0\" ADD \"" + OBJ_VALUE + + "\" failed on simple JSON array"); + } + for (final JsonPointer ptrAfter : ptrsAfter) { + final JsonArray outAfter = ptrAfter.add(in, OBJ_VALUE); + if (!assertEquals(checkAfter, outAfter)) { + result.fail("Pointer ADD operation", "Pointer \"/1\" ADD \"" + OBJ_VALUE + + "\" failed on simple JSON array"); + } + } + } + + /** + * Test pointer ADD operation for {@code JsonObject} on simple JSON array of + * size 2. Starting with an array of size 2. + * <ul> + * <li>Adding {@code JsonObject} at the end, in the middle and at the + * beginning of this array. + * <li>Adding {@code JsonObject} at the beginning, in the middle and at the + * end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testAddObjectOnSimpleArray2(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 2"); + final JsonArray in = createObjectArray2(); + final JsonArray check = createSimpleObjectArray5(); + verifyAddValues(result, in, check, new String[] { "/2", "/1", "/0" }, + new JsonObject[] { OBJ_VALUE_5, OBJ_VALUE_3, OBJ_VALUE_1 }, + "Pointer ADD operation", + "Pointers \"/2\", \"/1\", \"/0\" ADD sequence failed on simple JSON array"); + verifyAddValues(result, in, check, new String[] { "/0", "/2", "/4" }, + new JsonObject[] { OBJ_VALUE_1, OBJ_VALUE_3, OBJ_VALUE_5 }, + "Pointer ADD operation", + "Pointers \"/0\", \"/2\", \"/4\" ADD sequence failed on simple JSON array"); + } + + // Tests based on RFC 6902 definitions and examples. + + /** + * Test that existing target object is replaced by specified array when ADD + * operation is applied. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC 6902: + * 4.1. add</a>}:<br> + * When the operation is applied, the target location MUST reference one of: + * <ul> + * <li>A member to add to an existing object - whereupon the supplied value is + * added to that object at the indicated location. If the member already + * exists, it is replaced by the specified value.</li> + * <li>...</li> + * </ul> + */ + private void testAddArrayToReplaceObject(final TestResult result) { + System.out.println(" - for JsonArray to replace JsonObject"); + final JsonObject in = createCompoundObject(); + final JsonObject check = createCompoundObjectWithObjectReplaced(); + final JsonPointer ptr = Json.createPointer(DEF_OBJ_PATH); + final JsonArray replace = createSimpleStringArray5(); + final JsonObject out = ptr.add(in, replace); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + DEF_OBJ_PATH + + "\" ADD array to replace existing object failed on compound JSON object"); + } + } + + /** + * Test that whole document is replaced by specified array when ADD operation + * is applied with root pointer. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC 6902: + * 4.1. add</a>}:<br> + * When the operation is applied, the target location MUST reference one of: + * <ul> + * <li>The root of the target document - whereupon the specified value becomes + * the entire content of the target document.</li> + * <li>...</li> + * </ul> + */ + private void testAddArrayToReplaceDocument(final TestResult result) { + System.out.println(" - for JsonArray to replace whole document"); + final JsonObject in = createCompoundObject(); + final JsonArray check = createSimpleStringArray5(); + final JsonPointer ptr = Json.createPointer(""); + final JsonArray replace = createSimpleStringArray5(); + // Instance being replaced is JsonObject, instance being added is JsonArray + final JsonStructure out = ptr.add((JsonStructure) in, replace); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", "Pointer \"" + DEF_OBJ_PATH + + "\" ADD array to replace existing object failed on compound JSON object"); + } + } + + /** + * Test ADD operation of an array of {@code String}s into existing array of + * {@code String}s. This scenario is inspired by + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC 6902: + * 4.1. add</a>} operation example {@code { "op": "add", "path": "/a/b/c", + * "value": [ "foo", "bar" ] }} and following explanation of this operation on + * an array: + * <ul> + * <li>An element to add to an existing array - whereupon the supplied value + * is added to the array at the indicated location. Any elements at or above + * the specified index are shifted one position to the right. The specified + * index MUST NOT be greater than the number of elements in the array. If the + * "-" character is used to index the end of the array (see [RFC6901]), this + * has the effect of appending the value to the array.</li> + * </ul> + */ + private void testAddStringArrayToStringArray(final TestResult result) { + System.out.println(" - for String array to be added to existing String array"); + final JsonArray in = createStringArray2(); + final JsonArray check = createStringArray2WithStringArrayInTheMiddle(); + final JsonArray arrayToAdd = createStringInnerArray2(); + final JsonPointer ptr = Json.createPointer("/1"); + final JsonArray out = ptr.add(in, arrayToAdd); + if (!assertEquals(check, out)) { + result.fail("Pointer ADD operation", + "Pointer \"/1\" ADD array failed on JSON array"); + } + } + + /** + * Test ADD operation on non existing JsonObject. This scenario is described + * in {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC + * 6902: 4.1. add</a>} error handling samples. Test is trying to ADD value { + * "address" : "In a galaxy far far away"} into object { "name" : "John Smith" + * } using path "/child/address". Even "/child" path does not exist so this + * operation must fail. + * + */ + private void testAddStringToNonExistingObject(final TestResult result) { + System.out.println(" - for String to be added to non existing JsonObject"); + final JsonObject in = createSimpleObject(); + final JsonPointer ptr = Json.createPointer(DEF_OBJ_PATH + STR_PATH); + boolean exception = false; + try { + ptr.add(in, Json.createValue(STR_VALUE)); + } catch (JsonException e) { + exception = true; + System.out.println(" - Expected exception: " + e.getMessage()); + } + if (!exception) { + result.fail("Pointer ADD operation", + "ADD operation on non existing JsonObject \"" + DEF_OBJ_PATH + + "\" passed"); + } + } + + /** + * Test helper: Verify set of ADD operations on provided JSON array and verify + * result using provided expected JSON value. JSON pointer instance is used to + * modify the array. + * + * @param result + * Test suite result. + * @param in + * JSON array to be modified. + * @param check + * Expected modified JSON array (used for operation check). + * @param paths + * JSON array paths of values to be added. Pairs of {@code paths[i]} + * and {@code values[i]} are used for add operations. + * @param values + * JSON array values to be added on specified indexes. + * @param testName + * Name of this test. + * @param errorMessage + * Error message to be added on verification failure. + */ + private void verifyAddValues(final TestResult result, final JsonArray in, + final JsonArray check, final String[] paths, final Object[] values, + final String testName, final String errorMessage) { + if (paths.length != values.length) { + throw new IllegalArgumentException( + "Number of paths does not match number of indexes"); + } + JsonArray out = in; + for (int i = 0; i < paths.length; i++) { + final JsonPointer ptr = Json.createPointer(paths[i]); + out = ptr.add(out, toJsonValue(values[i])); + } + if (!assertEquals(check, out)) { + result.fail(testName, errorMessage); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerRemove.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerRemove.java new file mode 100644 index 0000000..3622a4e --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerRemove.java
@@ -0,0 +1,610 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.pointertests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * {@see <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>}: pointer + * usage for {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>} + * remove operation tests.<br> + */ +public class PointerRemove { + + /** + * Creates an instance of RFC 6901 pointer instance usage for RFC 6902 remove + * operation tests. + */ + PointerRemove() { + super(); + } + + /** + * Test RFC 6901 pointer instance usage for RFC 6902 remove operation. Suite + * entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "RFC 6901 pointer usage for RFC 6902 remove operation"); + System.out.println("Testing RFC 6901 pointer usage for RFC 6902 remove operation"); + testRemoveStringOnEmptyObject(result); + testRemoveStringOnEmptyArray(result); + testRemoveStringOnSimpleObject(result); + testRemoveStringOnSimpleArray(result); + testRemoveStringOnSimpleArray2(result); + testRemoveIntOnEmptyObject(result); + testRemoveIntOnEmptyArray(result); + testRemoveIntOnSimpleObject(result); + testRemoveIntOnSimpleArray(result); + testRemoveIntOnSimpleArray2(result); + testRemoveBoolOnEmptyObject(result); + testRemoveBoolOnEmptyArray(result); + testRemoveBoolOnSimpleObject(result); + testRemoveBoolOnSimpleArray(result); + testRemoveBoolOnSimpleArray2(result); + testRemoveObjectOnEmptyObject(result); + testRemoveObjectOnEmptyArray(result); + testRemoveObjectOnSimpleObject(result); + testRemoveObjectOnSimpleArray(result); + testRemoveObjectOnSimpleArray2(result); + testRemoveFromNonExistingLocationInObject(result); + testRemoveFromNonExistingLocationInArray(result); + return result; + } + + /** + * Test pointer REMOVE operation for {@code String} to produce empty JSON + * object. + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnEmptyObject(final TestResult result) { + System.out.println(" - for String to produce empty JSON object"); + final JsonObject in = createSimpleObjectStr(); + final JsonObject check = createEmptyObject(); + final JsonPointer ptr = Json.createPointer(STR_PATH); + final JsonObject out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", "Pointer \"" + STR_PATH + + "\" REMOVE failed when producing empty JSON object"); + } + } + + /** + * Test pointer REMOVE operation for {@code String} to produce empty JSON + * array. Only allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnEmptyArray(final TestResult result) { + System.out.println(" - for String to produce empty JSON array"); + final JsonArray in = createEmptyArrayWithStr(); + final JsonArray check = createEmptyArray(); + final JsonPointer ptr = Json.createPointer("/0"); + final JsonArray out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/0\" REMOVE failed when producing empty JSON array"); + } + } + + /** + * Test pointer REMOVE operation for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnSimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObjectWithStr(); + final JsonObject check = createSimpleObject(); + final JsonPointer ptr = Json.createPointer(STR_PATH); + final JsonObject out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", + "Pointer \"" + STR_PATH + "\" REMOVE failed on simple JSON object"); + } + } + + /** + * Test pointer REMOVE operation for {@code String} on simple JSON array of + * size 2. Using index {@code 0} to remove {@code String} before another + * existing element and index {@code 1} to remove {@code String} after another + * existing element. + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnSimpleArray(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 2"); + final JsonArray inBefore = createSimpleStringArrayWithStrBefore(); + final JsonArray inAfter = createSimpleStringArrayWithStrAfter(); + final JsonArray check = createStringArray1(); + final JsonPointer ptrBefore = Json.createPointer("/0"); + final JsonPointer ptrAfter = Json.createPointer("/1"); + final JsonArray outBefore = ptrBefore.remove(inBefore); + final JsonArray outAfter = ptrAfter.remove(inAfter); + if (!assertEquals(check, outBefore)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/0\" REMOVE failed on simple JSON array"); + } + if (!assertEquals(check, outAfter)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/1\" REMOVE failed on simple JSON array"); + } + } + + /** + * Test pointer REMOVE for {@code String} on simple JSON array of size 5. + * Starting with an array of size 2. + * <ul> + * <li>Removing {@code String} at the end, at the middle and at the beginning + * of this array. + * <li>Removing {@code String} at the beginning, in the middle and at the end + * of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testRemoveStringOnSimpleArray2(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 5"); + final JsonArray in = createSimpleStringArray5(); + final JsonArray check = createStringArray2(); + verifyRemoveValues(result, in, check, new String[] { "/4", "/2", "/0" }, + "Pointer REMOVE operation", + "Pointers \"/4\", \"/2\", \"/0\" REMOVE sequence failed on simple JSON array"); + verifyRemoveValues(result, in, check, new String[] { "/0", "/1", "/2" }, + "Pointer REMOVE operation", + "Pointers \"/0\", \"/1\", \"/2\" REMOVE sequence failed on simple JSON array"); + } + + /** + * Test pointer REMOVE operation for {@code int} to produce empty JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnEmptyObject(final TestResult result) { + System.out.println(" - for int to produce empty JSON object"); + final JsonObject in = createSimpleObjectInt(); + final JsonObject check = createEmptyObject(); + final JsonPointer ptr = Json.createPointer(INT_PATH); + final JsonObject out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", "Pointer \"" + INT_PATH + + "\" REMOVE failed when producing empty JSON object"); + } + } + + /** + * Test pointer REMOVE operation for {@code int} to produce empty JSON array. + * Only allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnEmptyArray(final TestResult result) { + System.out.println(" - for int to produce empty JSON array"); + final JsonArray in = createEmptyArrayWithInt(); + final JsonArray check = createEmptyArray(); + final JsonPointer ptr = Json.createPointer("/0"); + final JsonArray out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/0\" REMOVE failed when producing empty JSON array"); + } + } + + /** + * Test pointer REMOVE operation for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnSimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObjectWithInt(); + final JsonObject check = createSimpleObject(); + final JsonPointer ptr = Json.createPointer(INT_PATH); + final JsonObject out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", + "Pointer \"" + INT_PATH + "\" REMOVE failed on simple JSON object"); + } + } + + /** + * Test pointer REMOVE operation for {@code int} on simple JSON array of size + * 2. Using index {@code 0} to remove {@code int} before another existing + * element and index {@code 1} to remove {@code int} after another existing + * element. + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnSimpleArray(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 2"); + final JsonArray inBefore = createSimpleIntArrayWithIntBefore(); + final JsonArray inAfter = createSimpleIntArrayWithIntAfter(); + final JsonArray check = createIntArray1(); + final JsonPointer ptrBefore = Json.createPointer("/0"); + final JsonPointer ptrAfter = Json.createPointer("/1"); + final JsonArray outBefore = ptrBefore.remove(inBefore); + final JsonArray outAfter = ptrAfter.remove(inAfter); + if (!assertEquals(check, outBefore)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/0\" REMOVE failed on simple JSON array"); + } + if (!assertEquals(check, outAfter)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/1\" REMOVE failed on simple JSON array"); + } + } + + /** + * Test pointer REMOVE for {@code int} on simple JSON array of size 5. + * Starting with an array of size 5. + * <ul> + * <li>Removing {@code int} at the end, at the middle and at the beginning of + * this array. + * <li>Removing {@code int} at the beginning, in the middle and at the end of + * this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testRemoveIntOnSimpleArray2(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 5"); + final JsonArray in = createSimpleIntArray5(); + final JsonArray check = createIntArray2(); + verifyRemoveValues(result, in, check, new String[] { "/4", "/2", "/0" }, + "Pointer REMOVE operation", + "Pointers \"/4\", \"/2\", \"/0\" REMOVE sequence failed on simple JSON array"); + verifyRemoveValues(result, in, check, new String[] { "/0", "/1", "/2" }, + "Pointer REMOVE operation", + "Pointers \"/0\", \"/1\", \"/2\" REMOVE sequence failed on simple JSON array"); + } + + /** + * Test pointer REMOVE operation for {@code boolean} to produce empty JSON + * object. + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnEmptyObject(final TestResult result) { + System.out.println(" - for boolean to produce empty JSON object"); + final JsonObject in = createSimpleObjectBool(); + final JsonObject check = createEmptyObject(); + final JsonPointer ptr = Json.createPointer(BOOL_PATH); + final JsonObject out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", "Pointer \"" + BOOL_PATH + + "\" REMOVE failed when producing empty JSON object"); + } + } + + /** + * Test pointer REMOVE operation for {@code boolean} to produce empty JSON + * array. Only allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnEmptyArray(final TestResult result) { + System.out.println(" - for boolean to produce empty JSON array"); + final JsonArray in = createEmptyArrayWithBool(); + final JsonArray check = createEmptyArray(); + final JsonPointer ptr = Json.createPointer("/0"); + final JsonArray out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/0\" REMOVE failed when producing empty JSON array"); + } + } + + /** + * Test pointer REMOVE operation for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnSimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObjectWithBool(); + final JsonObject check = createSimpleObject(); + final JsonPointer ptr = Json.createPointer(BOOL_PATH); + final JsonObject out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", + "Pointer \"" + BOOL_PATH + "\" REMOVE failed on simple JSON object"); + } + } + + /** + * Test pointer REMOVE operation for {@code boolean} on simple JSON array of + * size 2. Using index {@code 0} to remove {@code boolean} before another + * existing element and index {@code 1} to remove {@code boolean} after + * another existing element. + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnSimpleArray(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 2"); + final JsonArray inBefore = createSimpleBoolArrayWithBoolBefore(); + final JsonArray inAfter = createSimpleBoolArrayWithBoolAfter(); + final JsonArray check = createBoolArray1(); + final JsonPointer ptrBefore = Json.createPointer("/0"); + final JsonPointer ptrAfter = Json.createPointer("/1"); + final JsonArray outBefore = ptrBefore.remove(inBefore); + final JsonArray outAfter = ptrAfter.remove(inAfter); + if (!assertEquals(check, outBefore)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/0\" REMOVE failed on simple JSON array"); + } + if (!assertEquals(check, outAfter)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/1\" REMOVE failed on simple JSON array"); + } + } + + /** + * Test pointer REMOVE for {@code boolean} on simple JSON array of size 5. + * Starting with an array of size 5. + * <ul> + * <li>Removing {@code boolean} at the end, at the middle and at the beginning + * of this array. + * <li>Removing {@code boolean} at the beginning, in the middle and at the end + * of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testRemoveBoolOnSimpleArray2(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 5"); + final JsonArray in = createSimpleBoolArray5(); + final JsonArray check = createBoolArray2(); + verifyRemoveValues(result, in, check, new String[] { "/4", "/2", "/0" }, + "Pointer REMOVE operation", + "Pointers \"/4\", \"/2\", \"/0\" REMOVE sequence failed on simple JSON array"); + verifyRemoveValues(result, in, check, new String[] { "/0", "/1", "/2" }, + "Pointer REMOVE operation", + "Pointers \"/0\", \"/1\", \"/2\" REMOVE sequence failed on simple JSON array"); + } + + /** + * Test pointer REMOVE operation for {@code JsonObject} to produce empty JSON + * object. + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnEmptyObject(final TestResult result) { + System.out.println(" - for JsonObject to produce empty JSON object"); + final JsonObject in = createSimpleObjectObject(); + final JsonObject check = createEmptyObject(); + final JsonPointer ptr = Json.createPointer(OBJ_PATH); + final JsonObject out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", "Pointer \"" + OBJ_PATH + + "\" REMOVE failed when producing empty JSON object"); + } + } + + /** + * Test pointer REMOVE operation for {@code JsonObject} to produce empty JSON + * array. Only allowed index for empty array is {@code 0}. + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnEmptyArray(final TestResult result) { + System.out.println(" - for JsonObject to produce empty JSON array"); + final JsonArray in = createEmptyArrayWithObject(); + final JsonArray check = createEmptyArray(); + final JsonPointer ptr = Json.createPointer("/0"); + final JsonArray out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/0\" REMOVE failed when producing empty JSON array"); + } + } + + /** + * Test pointer REMOVE operation for {@code JsonObject} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnSimpleObject(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON object"); + final JsonObject in = createCompoundObjectWithObject(); + final JsonObject check = createCompoundObject(); + final JsonPointer ptr = Json.createPointer(OBJ_PATH); + final JsonObject out = ptr.remove(in); + if (!assertEquals(check, out)) { + result.fail("Pointer REMOVE operation", + "Pointer \"" + OBJ_PATH + "\" REMOVE failed on simple JSON object"); + } + } + + /** + * Test pointer REMOVE operation for {@code JsonObject} on simple JSON array + * of size 2. Using index {@code 0} to remove {@code JsonObject} before + * another existing element and index {@code 1} to remove {@code JsonObject} + * after another existing element. + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnSimpleArray(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 2"); + final JsonArray inBefore = createSimpleObjectArrayWithObjectBefore(); + final JsonArray inAfter = createSimpleObjectArrayWithObjectAfter(); + final JsonArray check = createObjectArray1(); + final JsonPointer ptrBefore = Json.createPointer("/0"); + final JsonPointer ptrAfter = Json.createPointer("/1"); + final JsonArray outBefore = ptrBefore.remove(inBefore); + final JsonArray outAfter = ptrAfter.remove(inAfter); + if (!assertEquals(check, outBefore)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/0\" REMOVE failed on simple JSON array"); + } + if (!assertEquals(check, outAfter)) { + result.fail("Pointer REMOVE operation", + "Pointer \"/1\" REMOVE failed on simple JSON array"); + } + } + + /** + * Test pointer REMOVE for {@code JsonObject} on simple JSON array of size 5. + * Starting with an array of size 5. + * <ul> + * <li>Removing {@code JsonObject} at the end, at the middle and at the + * beginning of this array. + * <li>Removing {@code JsonObject} at the beginning, in the middle and at the + * end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testRemoveObjectOnSimpleArray2(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 5"); + final JsonArray in = createSimpleObjectArray5(); + final JsonArray check = createObjectArray2(); + verifyRemoveValues(result, in, check, new String[] { "/4", "/2", "/0" }, + "Pointer REMOVE operation", + "Pointers \"/4\", \"/2\", \"/0\" REMOVE sequence failed on simple JSON array"); + verifyRemoveValues(result, in, check, new String[] { "/0", "/1", "/2" }, + "Pointer REMOVE operation", + "Pointers \"/0\", \"/1\", \"/2\" REMOVE sequence failed on simple JSON array"); + } + + // Tests based on RFC 6902 definitions and examples. + + /** + * Test pointer REMOVE for non existing location in object. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.2">RFC 6902: + * 4.2. remove</a>} defines:<br> + * The target location MUST exist for the operation to be successful. + */ + private void testRemoveFromNonExistingLocationInObject( + final TestResult result) { + System.out.println(" - for non existing location in JsonObject"); + final JsonObject[] objsIn = new JsonObject[] { createEmptyObject(), + createSimpleObject(), createCompoundObject() }; + final String[] paths = new String[] { STR_PATH, INT_PATH, BOOL_PATH, + OBJ_PATH }; + // Go trough all objects + for (int i = 0; i < objsIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + final JsonPointer ptr = Json.createPointer(paths[j]); + try { + final JsonObject out = ptr.remove(objsIn[i]); + result.fail("Pointer REMOVE operation", "Pointer \"" + paths[j] + + "\" REMOVE succeeded on non existing location"); + } catch (JsonException e) { + // There are too many combinations to log them. + } + } + } + } + + /** + * Test pointer REMOVE for non existing location in array. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.2">RFC 6902: + * 4.2. remove</a>} defines:<br> + * The target location MUST exist for the operation to be successful. + */ + private void testRemoveFromNonExistingLocationInArray( + final TestResult result) { + System.out.println(" - for non existing location in JsonArray"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray1(), createIntArray2(), createSimpleBoolArray5(), + createObjectArray2() + + }; + final String[] paths = new String[] { "/", "/-1", "/-", "/5", "/0a", "/42", + STR_PATH + "/0" }; + // Go trough all arrays + for (int i = 0; i < arraysIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + final JsonPointer ptr = Json.createPointer(paths[j]); + try { + final JsonArray out = ptr.remove(arraysIn[i]); + result.fail("Pointer REMOVE operation", "Pointer \"" + paths[j] + + "\" REMOVE succeeded on non existing location"); + } catch (JsonException e) { + // There are too many combinations to log them. + } + } + } + } + + /** + * Test helper: Verify set of REMOVE operations on provided JSON array and + * verify result using provided expected JSON value. JSON pointer instance is + * used to modify the array. + * + * @param result + * Test suite result. + * @param in + * JSON array to be modified. + * @param check + * Expected modified JSON array (used for operation check). + * @param paths + * JSON array paths of values to be added. Pairs of {@code paths[i]} + * and {@code values[i]} are used for add operations. + * @param testName + * Name of this test. + * @param errorMessage + * Error message to be added on verification failure. + */ + private void verifyRemoveValues(final TestResult result, final JsonArray in, + final JsonArray check, final String[] paths, final String testName, + final String errorMessage) { + JsonArray out = in; + for (int i = 0; i < paths.length; i++) { + final JsonPointer ptr = Json.createPointer(paths[i]); + out = ptr.remove(out); + } + if (!assertEquals(check, out)) { + result.fail(testName, errorMessage); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerReplace.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerReplace.java new file mode 100644 index 0000000..0d9708d --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerReplace.java
@@ -0,0 +1,438 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.pointertests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * {@see <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>}: pointer + * usage for {@see <a href="https://tools.ietf.org/html/rfc6902">RFC 6902</a>} + * replace operation tests.<br> + */ +public class PointerReplace { + + /** + * Creates an instance of RFC 6901 pointer instance usage for RFC 6902 replace + * operation tests. + */ + PointerReplace() { + super(); + } + + /** + * Test RFC 6901 pointer instance usage for RFC 6902 replace operation. Suite + * entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult( + "RFC 6901 pointer usage for RFC 6902 replace operation"); + System.out.println( + "Testing RFC 6901 pointer usage for RFC 6902 replace operation"); + testReplaceStringOnSimpleObject(result); + testReplaceStringOnSimpleArray(result); + testReplaceStringOnSimpleArray2(result); + testReplaceIntOnSimpleObject(result); + testReplaceIntOnSimpleArray(result); + testReplaceIntOnSimpleArray2(result); + testReplaceBoolOnSimpleObject(result); + testReplaceBoolOnSimpleArray(result); + testReplaceBoolOnSimpleArray2(result); + testReplaceObjectOnCompoundObject(result); + testReplaceObjectOnSimpleArray(result); + testReplaceObjectOnSimpleArray2(result); + testReplaceOfNonExistingLocationInObject(result); + testReplaceOfNonExistingLocationInArray(result); + return result; + } + + /** + * Test pointer REPLACE operation for {@code String} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testReplaceStringOnSimpleObject(final TestResult result) { + System.out.println(" - for String on simple JSON object"); + final JsonObject in = createSimpleObjectStr(); + final JsonObject check = createSimpleObjectReplaceStr(); + final JsonPointer ptr = Json.createPointer(STR_PATH); + final JsonObject out = ptr.replace(in, Json.createValue(STR_VALUE2)); + if (!assertEquals(check, out)) { + result.fail("Pointer REPLACE operation", "Pointer \"" + STR_PATH + + "\" REPLACE \"" + STR_VALUE2 + "\" failed on simple JSON object"); + } + } + + /** + * Test pointer REPLACE operation for {@code String} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testReplaceStringOnSimpleArray(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 1"); + final JsonArray in = createStringArray1(); + final JsonArray check = createSimpleStringArrayReplaceStr(); + final JsonPointer ptr = Json.createPointer("/0"); + final JsonArray out = ptr.replace(in, Json.createValue(STR_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer REPLACE operation", "Pointer \"/0\" REPLACE \"" + + STR_VALUE + "\" failed on simple JSON array"); + } + } + + /** + * Test pointer REPLACE operation for {@code String} on simple JSON array of + * size 5. Starting with an array of size 5. + * <ul> + * <li>Replacing {@code String} items from the end to the beginning of this + * array. + * <li>Replacing {@code String} from the beginning to the end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testReplaceStringOnSimpleArray2(final TestResult result) { + System.out.println(" - for String on simple JSON array of size 5"); + final JsonArray in = createSimpleStringArray5(); + final JsonArray check = createSimpleStringArray5R(); + verifyReplaceValues(result, in, check, + new String[] { "/4", "/3", "/1", "/0" }, + new String[] { STR_VALUE_1, STR_VALUE_2, STR_VALUE_4, STR_VALUE_5 }, + "Pointer REPLACE operation", + "Pointers \"/4\", \"/3\", \"/1\", \"/0\" REPLACE sequence failed on simple JSON array"); + verifyReplaceValues(result, in, check, + new String[] { "/0", "/1", "/3", "/4" }, + new String[] { STR_VALUE_5, STR_VALUE_4, STR_VALUE_2, STR_VALUE_1 }, + "Pointer REPLACE operation", + "Pointers \"/0\", \"/1\", \"/3\", \"/4\" REPLACE sequence failed on simple JSON array"); + } + + /** + * Test pointer REPLACE operation for {@code int} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testReplaceIntOnSimpleObject(final TestResult result) { + System.out.println(" - for int on simple JSON object"); + final JsonObject in = createSimpleObjectInt(); + final JsonObject check = createSimpleObjectReplaceInt(); + final JsonPointer ptr = Json.createPointer(INT_PATH); + final JsonObject out = ptr.replace(in, Json.createValue(INT_VALUE2)); + if (!assertEquals(check, out)) { + result.fail("Pointer REPLACE operation", "Pointer \"" + INT_PATH + + "\" REPLACE \"" + INT_VALUE2 + "\" failed on simple JSON object"); + } + } + + /** + * Test pointer REPLACE operation for {@code int} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testReplaceIntOnSimpleArray(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 1"); + final JsonArray in = createIntArray1(); + final JsonArray check = createSimpleIntArrayReplaceInt(); + final JsonPointer ptr = Json.createPointer("/0"); + final JsonArray out = ptr.replace(in, Json.createValue(INT_VALUE)); + if (!assertEquals(check, out)) { + result.fail("Pointer REPLACE operation", "Pointer \"/0\" REPLACE \"" + + INT_VALUE + "\" failed on simple JSON array"); + } + } + + /** + * Test pointer REPLACE operation for {@code int} on simple JSON array of size + * 5. Starting with an array of size 5. + * <ul> + * <li>Replacing {@code int} items from the end to the beginning of this + * array. + * <li>Replacing {@code int} from the beginning to the end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testReplaceIntOnSimpleArray2(final TestResult result) { + System.out.println(" - for int on simple JSON array of size 5"); + final JsonArray in = createSimpleIntArray5(); + final JsonArray check = createSimpleIntArray5R(); + verifyReplaceValues(result, in, check, + new String[] { "/4", "/3", "/1", "/0" }, + new Integer[] { INT_VALUE_1, INT_VALUE_2, INT_VALUE_4, INT_VALUE_5 }, + "Pointer REPLACE operation", + "Pointers \"/4\", \"/3\", \"/1\", \"/0\" REPLACE sequence failed on simple JSON array"); + verifyReplaceValues(result, in, check, + new String[] { "/0", "/1", "/3", "/4" }, + new Integer[] { INT_VALUE_5, INT_VALUE_4, INT_VALUE_2, INT_VALUE_1 }, + "Pointer REPLACE operation", + "Pointers \"/0\", \"/1\", \"/3\", \"/4\" REPLACE sequence failed on simple JSON array"); + } + + /** + * Test pointer REPLACE operation for {@code boolean} on simple JSON object. + * + * @param result + * Tests result record. + */ + private void testReplaceBoolOnSimpleObject(final TestResult result) { + System.out.println(" - for boolean on simple JSON object"); + final JsonObject in = createSimpleObjectBool(); + final JsonObject check = createSimpleObjectReplaceBool(); + final JsonPointer ptr = Json.createPointer(BOOL_PATH); + final JsonObject out = ptr.replace(in, toJsonValue(BOOL_VALUE2)); + if (!assertEquals(check, out)) { + result.fail("Pointer REPLACE operation", "Pointer \"" + BOOL_PATH + + "\" REPLACE \"" + BOOL_VALUE2 + "\" failed on simple JSON object"); + } + } + + /** + * Test pointer REPLACE operation for {@code boolean} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testReplaceBoolOnSimpleArray(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 1"); + final JsonArray in = createBoolArray1(); + final JsonArray check = createSimpleBoolArrayReplaceBool(); + final JsonPointer ptr = Json.createPointer("/0"); + final JsonArray out = ptr.replace(in, toJsonValue(BOOL_FALSE)); + if (!assertEquals(check, out)) { + result.fail("Pointer REPLACE operation", "Pointer \"/0\" REPLACE \"" + + BOOL_FALSE + "\" failed on simple JSON array"); + } + } + + /** + * Test pointer REPLACE operation for {@code boolean} on simple JSON array of + * size 5. Starting with an array of size 5. + * <ul> + * <li>Replacing {@code boolean} items from the end to the beginning of this + * array. + * <li>Replacing {@code boolean} from the beginning to the end of this array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testReplaceBoolOnSimpleArray2(final TestResult result) { + System.out.println(" - for boolean on simple JSON array of size 5"); + final JsonArray in = createSimpleBoolArray5(); + final JsonArray check = createSimpleBoolArray5R(); + verifyReplaceValues(result, in, check, + new String[] { "/4", "/3", "/1", "/0" }, + new Boolean[] { BOOL_FALSE, BOOL_TRUE, BOOL_FALSE, BOOL_TRUE }, + "Pointer REPLACE operation", + "Pointers \"/4\", \"/3\", \"/1\", \"/0\" REPLACE sequence failed on simple JSON array"); + verifyReplaceValues(result, in, check, + new String[] { "/0", "/1", "/3", "/4" }, + new Boolean[] { BOOL_TRUE, BOOL_FALSE, BOOL_TRUE, BOOL_FALSE }, + "Pointer REPLACE operation", + "Pointers \"/0\", \"/1\", \"/3\", \"/4\" REPLACE sequence failed on simple JSON array"); + } + + /** + * Test pointer REPLACE operation for {@code JsonObject} on compound JSON + * object. + * + * @param result + * Tests result record. + */ + private void testReplaceObjectOnCompoundObject(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON object"); + final JsonObject in = createCompoundObjectWithObject(); + final JsonObject check = createCompoundObjectReplaceObject(); + final JsonPointer ptr = Json.createPointer(OBJ_PATH); + final JsonObject out = ptr.replace(in, OBJ_VALUE2); + if (!assertEquals(check, out)) { + result.fail("Pointer REPLACE operation", "Pointer \"" + OBJ_PATH + + "\" REPLACE \"" + OBJ_VALUE2 + "\" failed on simple JSON object"); + } + } + + /** + * Test pointer REPLACE operation for {@code JsonObject} on simple JSON array. + * + * @param result + * Tests result record. + */ + private void testReplaceObjectOnSimpleArray(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 1"); + final JsonArray in = createObjectArray1(); + final JsonArray check = createSimpleObjectArrayReplaceObject(); + final JsonPointer ptr = Json.createPointer("/0"); + final JsonArray out = ptr.replace(in, OBJ_VALUE); + if (!assertEquals(check, out)) { + result.fail("Pointer REPLACE operation", "Pointer \"/0\" REPLACE \"" + + OBJ_VALUE + "\" failed on simple JSON array"); + } + } + + /** + * Test pointer REPLACE operation for {@code JsonObject} on simple JSON array + * of size 5. Starting with an array of size 5. + * <ul> + * <li>Replacing {@code JsonObject} items from the end to the beginning of + * this array. + * <li>Replacing {@code JsonObject} from the beginning to the end of this + * array. + * </ul> + * + * @param result + * Tests result record. + */ + private void testReplaceObjectOnSimpleArray2(final TestResult result) { + System.out.println(" - for JsonObject on simple JSON array of size 5"); + final JsonArray in = createSimpleObjectArray5(); + final JsonArray check = createSimpleObjectArray5R(); + verifyReplaceValues(result, in, check, + new String[] { "/4", "/3", "/1", "/0" }, + new JsonObject[] { OBJ_VALUE_1, OBJ_VALUE_2, OBJ_VALUE_4, OBJ_VALUE_5 }, + "Pointer REPLACE operation", + "Pointers \"/4\", \"/3\", \"/1\", \"/0\" REPLACE sequence failed on simple JSON array"); + verifyReplaceValues(result, in, check, + new String[] { "/0", "/1", "/3", "/4" }, + new JsonObject[] { OBJ_VALUE_5, OBJ_VALUE_4, OBJ_VALUE_2, OBJ_VALUE_1 }, + "Pointer REPLACE operation", + "Pointers \"/0\", \"/1\", \"/3\", \"/4\" REPLACE sequence failed on simple JSON array"); + } + + // Tests based on RFC 6902 definitions and examples. + + /** + * Test pointer REPLACE for non existing location in object. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.3">RFC 6902: + * 4.3. replace</a>} defines:<br> + * The target location MUST exist for the operation to be successful. + */ + private void testReplaceOfNonExistingLocationInObject( + final TestResult result) { + System.out.println(" - for non existing location in JsonObject"); + final JsonObject[] objsIn = new JsonObject[] { createEmptyObject(), + createSimpleObject(), createCompoundObject() }; + final String[] paths = new String[] { STR_PATH, INT_PATH, BOOL_PATH, + OBJ_PATH }; + final JsonValue[] values = new JsonValue[] { Json.createValue(STR_VALUE), + Json.createValue(INT_VALUE), toJsonValue(BOOL_VALUE), OBJ_VALUE }; + // Go trough all objects + for (int i = 0; i < objsIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + final JsonPointer ptr = Json.createPointer(paths[j]); + try { + final JsonObject out = ptr.replace(objsIn[i], values[i]); + result.fail("Pointer REPLACE operation", "Pointer \"" + paths[j] + + "\" REPLACE succeeded on non existing location"); + } catch (JsonException e) { + // There are too many combinations to log them. + } + } + } + } + + /** + * Test pointer REPLACE for non existing location in array. + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.2">RFC 6902: + * 4.2. remove</a>} defines:<br> + * The target location MUST exist for the operation to be successful. + */ + private void testReplaceOfNonExistingLocationInArray( + final TestResult result) { + System.out.println(" - for non existing location in JsonArray"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray1(), createIntArray2(), createSimpleBoolArray5(), + createObjectArray2() + + }; + final String[] paths = new String[] { "/", "/-1", "/-", "/5", "/0a", "/42", + STR_PATH + "/0" }; + final JsonValue[] values = new JsonValue[] { Json.createValue(STR_VALUE), + Json.createValue(STR_VALUE), Json.createValue(INT_VALUE), + toJsonValue(BOOL_VALUE), OBJ_VALUE }; + // Go trough all arrays + for (int i = 0; i < arraysIn.length; i++) { + // Go trough all paths + for (int j = 0; j < paths.length; j++) { + final JsonPointer ptr = Json.createPointer(paths[j]); + try { + final JsonArray out = ptr.replace(arraysIn[i], values[i]); + result.fail("Pointer REPLACE operation", "Pointer \"" + paths[j] + + "\" REPLACE succeeded on non existing location"); + } catch (JsonException e) { + // There are too many combinations to log them. + } + } + } + } + + /** + * Test helper: Verify set of REPLACE operations on provided JSON array and + * verify result using provided expected JSON value. JSON pointer instance is + * used to modify the array. + * + * @param result + * Test suite result. + * @param in + * JSON array to be modified. + * @param check + * Expected modified JSON array (used for operation check). + * @param paths + * JSON array paths of values to be added. Pairs of {@code paths[i]} + * and {@code values[i]} are used for add operations. + * @param values + * JSON array values to be added on specified indexes. + * @param testName + * Name of this test. + * @param errorMessage + * Error message to be added on verification failure. + */ + private void verifyReplaceValues(final TestResult result, final JsonArray in, + final JsonArray check, final String[] paths, final Object[] values, + final String testName, final String errorMessage) { + if (paths.length != values.length) { + throw new IllegalArgumentException( + "Number of paths does not match number of indexes"); + } + JsonArray out = in; + for (int i = 0; i < paths.length; i++) { + final JsonPointer ptr = Json.createPointer(paths[i]); + out = ptr.replace(out, toJsonValue(values[i])); + } + if (!assertEquals(check, out)) { + result.fail(testName, errorMessage); + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerResolve.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerResolve.java new file mode 100644 index 0000000..130df0f --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerResolve.java
@@ -0,0 +1,622 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.pointertests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonException; +import jakarta.json.JsonObject; +import jakarta.json.JsonPointer; +import jakarta.json.JsonValue; + +import static jakarta.jsonp.tck.api.common.JsonAssert.*; +import static jakarta.jsonp.tck.api.common.PointerRFCObject.*; +import static jakarta.jsonp.tck.api.common.SimpleValues.*; + +// $Id$ +/** + * {@see <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>}: JavaScript + * Object Notation (JSON) Pointer resolving tests.<br> + */ +public class PointerResolve { + + /** + * Creates an instance of RFC 6901 JSON Pointer resolver tests. + */ + PointerResolve() { + super(); + } + + /** + * Test RFC 6901 JSON Pointer resolver tests. Suite entry point. + * + * @return Result of all tests in this suite. + */ + TestResult test() { + final TestResult result = new TestResult("RFC 6901 pointer resolving"); + System.out.println("Testing RFC 6901 pointer resolving"); + testResolveWholeDocument(result); + testResolveEmptyName(result); + testResolveSimpleArray(result); + testResolveSimpleArrayItems(result); + testResolvePathWithSlash(result); + testResolvePathWithEncodedSlash(result); + testResolvePathWithPercent(result); + testResolvePathWithCaret(result); + testResolvePathWithVerticalBar(result); + testResolvePathWithBackSlash(result); + testResolvePathWithDoubleQuotes(result); + testResolvePathWithSpace(result); + testResolvePathWithTilde(result); + testResolvePathWithEncodedTilde(result); + testResolvePathWithEncodedTildeOne(result); + testResolveValidNumericIndexInArray(result); + testResolveMemberAfterLastInArray(result); + testResolveNumericIndexWithLeadingZeroInArray(result); + testResolvenonNumericIndexInArray(result); + return result; + } + + /** + * Test RFC 6901 JSON Pointer resolver for the whole document path. + * + * @param result + * Tests result record. + */ + private void testResolveWholeDocument(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_KEY_WHOLE + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = in; + final JsonPointer ptr = Json.createPointer(RFC_KEY_WHOLE); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_KEY_WHOLE + "\"", + "GET operation failed for \"" + RFC_KEY_WHOLE + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_KEY_WHOLE + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "": 0}. + * + * @param result + * Tests result record. + */ + private void testResolveEmptyName(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR2 + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL2); + final JsonPointer ptr = Json.createPointer(RFC_PTR2); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR2 + "\"", + "GET operation failed for \"" + RFC_PTR2 + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_PTR2 + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "foo": ["bar", "baz"]}. + * + * @param result + * Tests result record. + */ + private void testResolveSimpleArray(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR1 + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = RFC_VAL1; + final JsonPointer ptr = Json.createPointer(RFC_PTR1); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR1 + "\"", + "GET operation failed for \"" + RFC_PTR1 + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_PTR1 + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "foo": ["bar", "baz"]} array + * elements. + * + * @param result + * Tests result record. + */ + private void testResolveSimpleArrayItems(final TestResult result) { + final String[] itemPtrs = new String[] { RFC_PTR1_ITEM1, RFC_PTR1_ITEM2 }; + final String[] itemVals = new String[] { RFC_VAL1_ITEM1, RFC_VAL1_ITEM2 }; + final JsonObject in = createRFC6901Object(); + for (int i = 0; i < itemPtrs.length; i++) { + System.out.println(" - resolving of \"" + itemPtrs[i] + "\" pointer"); + final JsonValue check = Json.createValue(itemVals[i]); + final JsonPointer ptr = Json.createPointer(itemPtrs[i]); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + itemPtrs[i] + "\"", + "GET operation failed for \"" + itemPtrs[i] + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + itemPtrs[i] + "\"", + "GET operation exception: " + e.getMessage()); + } + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "a/b": 1}. Character + * {@code '/'} is encoded as {@code "~1"} string. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithEncodedSlash(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR3_ENC + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL3); + final JsonPointer ptr = Json.createPointer(RFC_PTR3_ENC); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR3_ENC + "\"", + "GET operation failed for \"" + RFC_PTR3_ENC + "\" path"); + } + } catch (JsonException e) { + System.out.println(" ! Exception: " + e.getMessage()); + result.fail("GET \"" + RFC_PTR3_ENC + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "a/b": 1}. Character + * {@code '/'} is not encoded as {@code "~1"} string. This results in invalid + * {@code "/a/b"} path and resolving such path must throw an exception. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithSlash(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR3 + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonPointer ptr = Json.createPointer(RFC_PTR3); + try { + final JsonValue out = ptr.getValue(in); + result.fail("GET \"" + RFC_PTR3 + "\"", + "GET operation succeeded for \"" + RFC_PTR3 + "\" path"); + } catch (JsonException e) { + System.out.println(" - Expected exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "c%d": 2}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithPercent(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR4 + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL4); + final JsonPointer ptr = Json.createPointer(RFC_PTR4); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR4 + "\"", + "GET operation failed for \"" + RFC_PTR4 + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_PTR4 + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "e^f": 3}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithCaret(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR5 + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL5); + final JsonPointer ptr = Json.createPointer(RFC_PTR5); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR5 + "\"", + "GET operation failed for \"" + RFC_PTR5 + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_PTR5 + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "g|h": 4}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithVerticalBar(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR6 + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL6); + final JsonPointer ptr = Json.createPointer(RFC_PTR6); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR6 + "\"", + "GET operation failed for \"" + RFC_PTR6 + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_PTR6 + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "i\\j": 5}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithBackSlash(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR7 + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL7); + final JsonPointer ptr = Json.createPointer(RFC_PTR7); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR7 + "\"", + "GET operation failed for \"" + RFC_PTR7 + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_PTR7 + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "k\"l": 6}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithDoubleQuotes(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR8 + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL8); + final JsonPointer ptr = Json.createPointer(RFC_PTR8); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR8 + "\"", + "GET operation failed for \"" + RFC_PTR8 + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_PTR8 + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code " ": 7}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithSpace(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR9 + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL9); + final JsonPointer ptr = Json.createPointer(RFC_PTR9); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR9 + "\"", + "GET operation failed for \"" + RFC_PTR9 + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_PTR9 + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "m~n": 8} without encoding. + * Passing this test is not mandatory. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-3">RFC 6901: 3. + * Syntax</a>} defines JSON pointer grammar as:<br> + * {@code json-pointer = *( "/" reference-token )}<br> + * {@code reference-token = *( unescaped / escaped )}<br> + * {@code unescaped = %x00-2E / %x30-7D / %x7F-10FFFF}<br> + * {@code escaped = "~" ( "0" / "1" )}<br> + * Characters {@code '/'} and {@code '~'} are excluded from {@code unescaped}. + * But having {@code '~'} outside escape sequence may be acceptable. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithTilde(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR10 + "\" pointer (optional)"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL10); + final JsonPointer ptr = Json.createPointer(RFC_PTR10); + boolean noError = true; + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + noError = false; + System.out.println(" - Pointer \"" + RFC_KEY10 + + "\" did not return expected value"); + } + } catch (JsonException e) { + noError = false; + System.out.println(" - Expected exception: " + e.getMessage()); + } + if (noError) { + System.out.println( + " - Pointer resolving accepts '~' outside escape sequence"); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "m~n": 8}. Character + * {@code '~'} is encoded as {@code "~0"} string. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithEncodedTilde(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_KEY10_ENC + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL10); + final JsonPointer ptr = Json.createPointer(RFC_KEY10_ENC); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_KEY10_ENC + "\"", + "GET operation failed for \"" + RFC_KEY10_ENC + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_KEY10_ENC + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for {@code "o~1p": 9}. String + * {@code "~1"} is encoded as {@code "~01"} String. Proper encoded sequences + * transformation is described in + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-4">RFC 6901: 4. + * Evaluation</a>} chapter: + * {@code "the string '~01' correctly becomes '~1' after transformation"}. + * + * @param result + * Tests result record. + */ + private void testResolvePathWithEncodedTildeOne(final TestResult result) { + System.out.println(" - resolving of \"" + RFC_PTR11_ENC + "\" pointer"); + final JsonObject in = createRFC6901Object(); + final JsonValue check = Json.createValue(RFC_VAL11); + final JsonPointer ptr = Json.createPointer(RFC_PTR11_ENC); + try { + final JsonValue out = ptr.getValue(in); + if (!assertEquals(out, check)) { + result.fail("GET \"" + RFC_PTR11_ENC + "\"", + "GET operation failed for \"" + RFC_PTR11_ENC + "\" path"); + } + } catch (JsonException e) { + result.fail("GET \"" + RFC_PTR11_ENC + "\"", + "GET operation exception: " + e.getMessage()); + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for existing numeric indexes of an + * array. {@see <a href="https://tools.ietf.org/html/rfc6901#section-4">RFC + * 6901: 4. Evaluation</a>} chapter:<br> + * If the currently referenced value is a JSON array, the reference token MUST + * contain either: + * <ul> + * <li>characters comprised of digits (see ABNF below; note that leading zeros + * are not allowed) that represent an unsigned base-10 integer value, making + * the new referenced value the array element with the zero-based index + * identified by the token</li> + * </ul> + */ + private void testResolveValidNumericIndexInArray(final TestResult result) { + System.out.println( + " - resolving of pointer containing existing numeric array index"); + final JsonArray[] arraysIn = new JsonArray[] { createSimpleStringArray5(), + createSimpleIntArray5(), createSimpleBoolArray5(), + createSimpleObjectArray5() }; + final JsonValue[] strings = new JsonValue[] { toJsonValue(STR_VALUE_1), + toJsonValue(STR_VALUE_2), toJsonValue(STR_VALUE_3), + toJsonValue(STR_VALUE_4), toJsonValue(STR_VALUE_5) }; + final JsonValue[] ints = new JsonValue[] { toJsonValue(INT_VALUE_1), + toJsonValue(INT_VALUE_2), toJsonValue(INT_VALUE_3), + toJsonValue(INT_VALUE_4), toJsonValue(INT_VALUE_5) }; + final JsonValue[] bools = new JsonValue[] { toJsonValue(BOOL_FALSE), + toJsonValue(BOOL_TRUE), toJsonValue(BOOL_TRUE), toJsonValue(BOOL_FALSE), + toJsonValue(BOOL_TRUE) }; + final JsonValue[] objs = new JsonValue[] { OBJ_VALUE_1, OBJ_VALUE_2, + OBJ_VALUE_3, OBJ_VALUE_4, OBJ_VALUE_5 }; + final JsonValue[][] checks = new JsonValue[][] { strings, ints, bools, + objs }; + // Go trough all array types + for (int i = 0; i < arraysIn.length; i++) { + // Go trough all valid indexes in arrays + for (int j = 0; j < 5; j++) { + final String path = "/" + Integer.toString(j); + final JsonPointer ptr = Json.createPointer(path); + final JsonValue out = ptr.getValue(arraysIn[i]); + if (!assertEquals(out, checks[i][j])) { + JsonValue.ValueType type = checks[i][j].getValueType(); + String typeName = type == JsonValue.ValueType.TRUE + || type == JsonValue.ValueType.FALSE ? "boolean" + : type.toString().toLowerCase(); + result.fail("GET \"" + path + "\"", "GET operation failed for \"" + + path + "\" path on " + typeName + " array"); + } + } + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for character {@code '-'} marking the + * end of an array. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-4">RFC 6901: 4. + * Evaluation</a>} chapter:<br> + * If the currently referenced value is a JSON array, the reference token MUST + * contain either: + * <ul> + * <li>exactly the single character "-", making the new referenced value the + * (nonexistent) member after the last array element</li> + * </ul> + * Note that the use of the "-" character to index an array will always result + * in such an error condition because by definition it refers to a nonexistent + * array element. Thus, applications of JSON Pointer need to specify how that + * character is to be handled, if it is to be useful. + */ + private void testResolveMemberAfterLastInArray(final TestResult result) { + System.out.println(" - resolving of array \"/-\" pointer"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray(), createSimpleIntArray5(), createBoolArray2(), + createSimpleObjectArray5() }; + final String[] typeNames = new String[] { "empty", "String", "int", + "boolean", "JsonObject" }; + // Go trough all array types + for (int i = 0; i < arraysIn.length; i++) { + final JsonPointer ptr = Json.createPointer("/-"); + try { + final JsonValue out = ptr.getValue(arraysIn[i]); + result.fail("GET \"/-\"", "GET operation succeeded for \"/-\" key"); + } catch (JsonException e) { + System.out.println(" - Expected exception for \"/-\" path in " + + typeNames[i] + " array: " + e.getMessage()); + } + } + } + + // TODO: Consider whether passing this test is mandatory or optional. + /** + * Test RFC 6901 JSON Pointer resolver for existing index with leading + * {@code '0'} on array. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-4">RFC 6901: 4. + * Evaluation</a>} chapter:<br> + * {@code array-index = %x30 / ( %x31-39 *(%x30-39) )} grammar rule prohibits + * indexes with leading {@code '0'} except the case when index is exactly + * {@code "0"}. Exact case for {@code "0"} is being checked in other tests. + * This test checks illegal values with leading {@code '0'} followed by valid + * index numbers. + */ + private void testResolveNumericIndexWithLeadingZeroInArray( + final TestResult result) { + System.out.println( + " - resolving of pointer containing numeric array index with leading '0' (optional)"); + final JsonArray[] arraysIn = new JsonArray[] { createSimpleStringArray5(), + createSimpleIntArray5(), createSimpleBoolArray5(), + createSimpleObjectArray5() }; + final String[] typeNames = new String[] { "String", "int", "boolean", + "JsonObject" }; + // Go trough all array types + for (int i = 0; i < arraysIn.length; i++) { + // Go trough all valid indexes in arrays + for (int j = 0; j < 5; j++) { + final String path = "/0" + Integer.toString(j); + final JsonPointer ptr = Json.createPointer(path); + try { + final JsonValue out = ptr.getValue(arraysIn[i]); + System.out.println(" ! GET operation succeeded for \"" + path + + "\" path on " + typeNames[i] + " array"); + // result.fail("GET \""+path+"\"", + // "GET operation succeeded for \""+path+"\" key on "+typeNames[i]+" + // array"); + } catch (JsonException e) { + // There are too many combinations to log them. + } + } + } + } + + /** + * Test RFC 6901 JSON Pointer resolver for invalid index containing non + * numeric characters on array. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-4">RFC 6901: 4. + * Evaluation</a>} chapter:<br> + * {@code array-index = %x30 / ( %x31-39 *(%x30-39) )} grammar rule prohibits + * indexes with anything else than sequence of digits. Index {@code '-'} is + * being checked in another tests. The only exception is path for whole + * document ({@code ""}) which must return the whole array. + */ + private void testResolvenonNumericIndexInArray(final TestResult result) { + System.out.println(" - resolving of pointer containing non numeric array index"); + final JsonArray[] arraysIn = new JsonArray[] { createEmptyArray(), + createStringArray(), createSimpleIntArray5(), createBoolArray2(), + createSimpleObjectArray5() }; + final String[] typeNames = new String[] { "empty", "String", "int", + "boolean", "JsonObject" }; + final String wholeDocument = ""; + final String[] paths = new String[] { "/", "/1a", "/b4", "/name" }; + // Go trough all array types + for (int i = 0; i < arraysIn.length; i++) { + final JsonPointer wholeDocPtr = Json.createPointer(wholeDocument); + try { + final JsonValue wholeOut = wholeDocPtr.getValue(arraysIn[i]); + if (!assertEquals(wholeOut, arraysIn[i])) { + result.fail("GET \"" + wholeDocument + "\"", + "GET operation failed for \"" + wholeDocument + "\" path on " + + typeNames[i] + " array"); + } + } catch (JsonException e) { + result.fail("GET \"" + wholeDocument + "\"", + "GET operation failed for \"" + wholeDocument + "\" path on " + + typeNames[i] + " array: " + e.getMessage()); + } + for (int j = 0; j < paths.length; j++) { + final JsonPointer ptr = Json.createPointer(paths[j]); + try { + final JsonValue out = ptr.getValue(arraysIn[i]); + result.fail("GET \"" + paths[j] + "\"", + "GET operation succeeded for \"" + paths[j] + "\" path on " + + typeNames[i] + " array"); + } catch (JsonException e) { + // There are too many combinations to log them. + } + } + } + } + +}
diff --git a/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerTests.java b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerTests.java new file mode 100644 index 0000000..571fe47 --- /dev/null +++ b/tck/tck-tests/src/main/java/jakarta/jsonp/tck/api/pointertests/PointerTests.java
@@ -0,0 +1,132 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package jakarta.jsonp.tck.api.pointertests; + +import jakarta.jsonp.tck.api.common.TestResult; +import jakarta.jsonp.tck.lib.harness.Fault; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +// $Id$ +/** + * {@see <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>}: JavaScript + * Object Notation (JSON) Pointer compatibility tests.<br> + * JSON-P API defines {@link jakarta.json.JsonPointer} interface to work with RFC + * 6901 JSON Pointer. + */ +@RunWith(Arquillian.class) +public class PointerTests { + + @Deployment + public static WebArchive createTestArchive() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, PointerTests.class.getPackage().getName()); + } + /** + * Test JSON-P API response on pointer resolving.<br> + * Checks set of JSON pointers from sample object of RFC 6901. + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-4">RFC 6901: 4. + * Evaluation</a>} and + * {@see <a href="https://tools.ietf.org/html/rfc6901#section-5">RFC 6901: 5. + * JSON String Representation</a>}. + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPointerResolveTest + * @assertion_ids: JSONP:JAVADOC:643; JSONP:JAVADOC:582; JSONP:JAVADOC:583; + * JSONP:JAVADOC:584; JSONP:JAVADOC:661; JSONP:JAVADOC:662; + * JSONP:JAVADOC:663; + * @test_Strategy: Test API response on various JSON pointer values. + */ + @Test + public void jsonPointerResolveTest() throws Fault { + PointerResolve resolveTest = new PointerResolve(); + final TestResult result = resolveTest.test(); + result.eval(); + } + + /** + * Test JSON-P API response on + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.1">RFC 6902: + * 4.1. add</a>} operation using RFC 6901 pointer instance.<br> + * Checks set of simple JSON values.<br> + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPointerAddOperationTest + * @assertion_ids: JSONP:JAVADOC:642; JSONP:JAVADOC:582; JSONP:JAVADOC:583; + * JSONP:JAVADOC:584; JSONP:JAVADOC:661; JSONP:JAVADOC:662; + * JSONP:JAVADOC:663; + * @test_Strategy: Test API response on various JSON pointer values. + */ + @Test + public void jsonPointerAddOperationTest() throws Fault { + PointerAdd addTest = new PointerAdd(); + final TestResult result = addTest.test(); + result.eval(); + } + + /** + * Test JSON-P API response on + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.2">RFC 6902: + * 4.2. remove</a>} operation using RFC 6901 pointer instance.<br> + * Checks set of simple JSON values.<br> + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPointerRemoveOperationTest + * @assertion_ids: JSONP:JAVADOC:644; JSONP:JAVADOC:582; JSONP:JAVADOC:661; + * @test_Strategy: Test API response on various JSON pointer values. + */ + @Test + public void jsonPointerRemoveOperationTest() throws Fault { + PointerRemove removeTest = new PointerRemove(); + final TestResult result = removeTest.test(); + result.eval(); + } + + /** + * Test JSON-P API response on + * {@see <a href="https://tools.ietf.org/html/rfc6902#section-4.3">RFC 6902: + * 4.3. replace</a>} operation using RFC 6901 pointer instance.<br> + * Checks set of simple JSON values.<br> + * + * @throws Fault + * when this test failed. + * + * @testName: jsonPointerReplaceOperationTest + * @assertion_ids: JSONP:JAVADOC:645; JSONP:JAVADOC:582; JSONP:JAVADOC:583; + * JSONP:JAVADOC:584; JSONP:JAVADOC:661; JSONP:JAVADOC:662; + * JSONP:JAVADOC:663; + * @test_Strategy: Test API response on various JSON pointer values. + */ + @Test + public void jsonPointerReplaceOperationTest() throws Fault { + PointerReplace replaceTest = new PointerReplace(); + final TestResult result = replaceTest.test(); + result.eval(); + } + +}
diff --git a/tck/tck-tests/src/main/resources/jsonArrayUTF16BE.json b/tck/tck-tests/src/main/resources/jsonArrayUTF16BE.json new file mode 100644 index 0000000..69c0e86 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonArrayUTF16BE.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonArrayUTF8.json b/tck/tck-tests/src/main/resources/jsonArrayUTF8.json new file mode 100644 index 0000000..3736875 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonArrayUTF8.json
@@ -0,0 +1 @@ +["a旨䔬讞斉屗列z"] \ No newline at end of file
diff --git a/tck/tck-tests/src/main/resources/jsonArrayWithAllTypesOfData.json b/tck/tck-tests/src/main/resources/jsonArrayWithAllTypesOfData.json new file mode 100644 index 0000000..b7e3a59 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonArrayWithAllTypesOfData.json
@@ -0,0 +1,36 @@ +[ + "", + [], + {}, + "string", + 100, + true, + false, + null, + { + "emptyString" : "", + "emptyArray" : [], + "emptyObject" : {}, + "string" : "string", + "number" : 100, + "true" : true, + "false" : false, + "null" : null, + "object" : { "name" : "value" }, + "array" : [ "one", "two" ] + }, + [ "string", 100, true, false, null, { "name" : "value" }, [ "one", "two" ] ], + 100, + -100, + 9223372036854775807, + -9223372036854775808, + 0.5, + -0.5, + 7e3, + 7e+3, + 9E3, + 9E+3, + 7e-3, + 7E-3, + "!@#$%^&*()_+|~1234567890-=;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" +]
diff --git a/tck/tck-tests/src/main/resources/jsonArrayWithAllTypesOfDataUTF16BE.json b/tck/tck-tests/src/main/resources/jsonArrayWithAllTypesOfDataUTF16BE.json new file mode 100644 index 0000000..8263796 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonArrayWithAllTypesOfDataUTF16BE.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonArrayWithEscapeCharsData.json b/tck/tck-tests/src/main/resources/jsonArrayWithEscapeCharsData.json new file mode 100644 index 0000000..4f2084d --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonArrayWithEscapeCharsData.json
@@ -0,0 +1,3 @@ +[ + "popeye\"\\\/\b\f\n\r\tolive" +]
diff --git a/tck/tck-tests/src/main/resources/jsonArrayWithLotsOfNestedArraysData.json b/tck/tck-tests/src/main/resources/jsonArrayWithLotsOfNestedArraysData.json new file mode 100644 index 0000000..9ef74ba --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonArrayWithLotsOfNestedArraysData.json
@@ -0,0 +1,92 @@ +[ + [ + "name1","value1", + "nested2",[ + "name2","value2", + "nested3",[ + "name3","value3", + "nested4",[ + "name4","value4", + "nested5",[ + "name5","value5", + "nested6",[ + "name6","value6", + "nested7",[ + "name7","value7", + "nested8",[ + "name8","value8", + "nested9",[ + "name9","value9", + "nested10",[ + "name10","value10", + "nested11",[ + "name11","value11", + "nested12",[ + "name12","value12", + "nested13",[ + "name13","value13", + "nested14",[ + "name14","value14", + "nested15",[ + "name15","value15", + "nested16",[ + "name16","value16", + "nested17",[ + "name17","value17", + "nested18",[ + "name18","value18", + "nested19",[ + "name19","value19", + "nested20",[ + "name20","value20", + "nested21",[ + "name21","value21", + "nested22",[ + "name22","value22", + "nested23",[ + "name23","value23", + "nested24",[ + "name24","value24", + "nested25",[ + "name25","value25", + "nested26",[ + "name26","value26", + "nested27",[ + "name27","value27", + "nested28",[ + "name28","value28", + "nested29",[ + "name29","value29", + "nested30",[ + "name30","value30" + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] +]
diff --git a/tck/tck-tests/src/main/resources/jsonArrayWithLotsOfNestedObjectsData.json b/tck/tck-tests/src/main/resources/jsonArrayWithLotsOfNestedObjectsData.json new file mode 100644 index 0000000..f97781f --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonArrayWithLotsOfNestedObjectsData.json
@@ -0,0 +1,92 @@ +[ + { + "name1" : "value1", + "nested2" : { + "name2" : "value2", + "nested3" : { + "name3" : "value3", + "nested4" : { + "name4" : "value4", + "nested5" : { + "name5" : "value5", + "nested6" : { + "name6" : "value6", + "nested7" : { + "name7" : "value7", + "nested8" : { + "name8" : "value8", + "nested9" : { + "name9" : "value9", + "nested10" : { + "name10" : "value10", + "nested11" : { + "name11" : "value11", + "nested12" : { + "name12" : "value12", + "nested13" : { + "name13" : "value13", + "nested14" : { + "name14" : "value14", + "nested15" : { + "name15" : "value15", + "nested16" : { + "name16" : "value16", + "nested17" : { + "name17" : "value17", + "nested18" : { + "name18" : "value18", + "nested19" : { + "name19" : "value19", + "nested20" : { + "name20" : "value20", + "nested21" : { + "name21" : "value21", + "nested22" : { + "name22" : "value22", + "nested23" : { + "name23" : "value23", + "nested24" : { + "name24" : "value24", + "nested25" : { + "name25" : "value25", + "nested26" : { + "name26" : "value26", + "nested27" : { + "name27" : "value27", + "nested28" : { + "name28" : "value28", + "nested29" : { + "name29" : "value29", + "nested30" : { + "name30" : "value30" + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +]
diff --git a/tck/tck-tests/src/main/resources/jsonHelloWorld.json b/tck/tck-tests/src/main/resources/jsonHelloWorld.json new file mode 100644 index 0000000..9049ffd --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonHelloWorld.json
@@ -0,0 +1,4 @@ +{ + "greetingObj":{"hello":"world"}, + "greetingArr":["hello","world"] +}
diff --git a/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF16.json b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF16.json new file mode 100644 index 0000000..fe2f539 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF16.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF16BE.json b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF16BE.json new file mode 100644 index 0000000..d1ddcf5 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF16BE.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF16LE.json b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF16LE.json new file mode 100644 index 0000000..c48ec6f --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF16LE.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF32BE.json b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF32BE.json new file mode 100644 index 0000000..cc6e10e --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF32BE.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF32LE.json b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF32LE.json new file mode 100644 index 0000000..92c853c --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF32LE.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF8.json b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF8.json new file mode 100644 index 0000000..ef3478f --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectEncodingUTF8.json
@@ -0,0 +1 @@ +{"stringName":"stringValue","objectName":{"foo":"bar"},"arrayName":[1,2,3]}
diff --git a/tck/tck-tests/src/main/resources/jsonObjectUTF16LE.json b/tck/tck-tests/src/main/resources/jsonObjectUTF16LE.json new file mode 100644 index 0000000..9fb29a8 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectUTF16LE.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonObjectUTF8.json b/tck/tck-tests/src/main/resources/jsonObjectUTF8.json new file mode 100644 index 0000000..e40bd76 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectUTF8.json
@@ -0,0 +1 @@ +{"unicodeChars":"a旨䔬讞斉屗列z"} \ No newline at end of file
diff --git a/tck/tck-tests/src/main/resources/jsonObjectUnknownEncoding.json b/tck/tck-tests/src/main/resources/jsonObjectUnknownEncoding.json new file mode 100644 index 0000000..f76dd23 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectUnknownEncoding.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonObjectWithAllTypesOfData.json b/tck/tck-tests/src/main/resources/jsonObjectWithAllTypesOfData.json new file mode 100644 index 0000000..1e92477 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectWithAllTypesOfData.json
@@ -0,0 +1,36 @@ +{ + "emptyString" : "", + "emptyArray" : [], + "emptyObject" : {}, + "string" : "string", + "number" : 100, + "true" : true, + "false" : false, + "null" : null, + "object" : { + "emptyString" : "", + "emptyArray" : [], + "emptyObject" : {}, + "string" : "string", + "number" : 100, + "true" : true, + "false" : false, + "null" : null, + "object" : { "name" : "value" }, + "array" : [ "one", "two" ] + }, + "array" : [ "string", 100, true, false, null, { "name" : "value" }, [ "one", "two" ] ], + "intPositive" : 100, + "intNegative" : -100, + "longMax" : 9223372036854775807, + "longMin" : -9223372036854775808, + "fracPositive" : 0.5, + "fracNegative" : -0.5, + "expPositive1" : 7e3, + "expPositive2" : 7e+3, + "expPositive3" : 9E3, + "expPositive4" : 9E+3, + "expNegative1" : 7e-3, + "expNegative2" : 7E-3, + "asciiChars" : "!@#$%^&*()_+|~1234567890-=;',./<>? qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" +}
diff --git a/tck/tck-tests/src/main/resources/jsonObjectWithAllTypesOfDataUTF16LE.json b/tck/tck-tests/src/main/resources/jsonObjectWithAllTypesOfDataUTF16LE.json new file mode 100644 index 0000000..a2c1b53 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectWithAllTypesOfDataUTF16LE.json Binary files differ
diff --git a/tck/tck-tests/src/main/resources/jsonObjectWithEscapeCharsData.json b/tck/tck-tests/src/main/resources/jsonObjectWithEscapeCharsData.json new file mode 100644 index 0000000..b043d7b --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectWithEscapeCharsData.json
@@ -0,0 +1,3 @@ +{ + "escapeChars" : "popeye\"\\\/\b\f\n\r\tolive" +}
diff --git a/tck/tck-tests/src/main/resources/jsonObjectWithLotsOfNestedObjectsData.json b/tck/tck-tests/src/main/resources/jsonObjectWithLotsOfNestedObjectsData.json new file mode 100644 index 0000000..3ac34d6 --- /dev/null +++ b/tck/tck-tests/src/main/resources/jsonObjectWithLotsOfNestedObjectsData.json
@@ -0,0 +1,92 @@ +{ + "nested1" : { + "name1" : "value1", + "nested2" : { + "name2" : "value2", + "nested3" : { + "name3" : "value3", + "nested4" : { + "name4" : "value4", + "nested5" : { + "name5" : "value5", + "nested6" : { + "name6" : "value6", + "nested7" : { + "name7" : "value7", + "nested8" : { + "name8" : "value8", + "nested9" : { + "name9" : "value9", + "nested10" : { + "name10" : "value10", + "nested11" : { + "name11" : "value11", + "nested12" : { + "name12" : "value12", + "nested13" : { + "name13" : "value13", + "nested14" : { + "name14" : "value14", + "nested15" : { + "name15" : "value15", + "nested16" : { + "name16" : "value16", + "nested17" : { + "name17" : "value17", + "nested18" : { + "name18" : "value18", + "nested19" : { + "name19" : "value19", + "nested20" : { + "name20" : "value20", + "nested21" : { + "name21" : "value21", + "nested22" : { + "name22" : "value22", + "nested23" : { + "name23" : "value23", + "nested24" : { + "name24" : "value24", + "nested25" : { + "name25" : "value25", + "nested26" : { + "name26" : "value26", + "nested27" : { + "name27" : "value27", + "nested28" : { + "name28" : "value28", + "nested29" : { + "name29" : "value29", + "nested30" : { + "name30" : "value30" + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +}