diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index ad3b7e355..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,58 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/2.0/configuration-reference -version: 2.1 - -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/2.0/configuration-reference/#jobs -jobs: - # Below is the definition of your job to build and test your app, you can rename and customize it as you want. - build-and-test: - # These next lines define a Docker executor: https://circleci.com/docs/2.0/executor-types/ - # You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. - # Be sure to update the Docker image tag below to openjdk version of your application. - # A list of available CircleCI Docker Convenience Images are available here: https://circleci.com/developer/images/image/cimg/openjdk - docker: - - image: cimg/openjdk:17.0 - # Add steps to the job - # See: https://circleci.com/docs/2.0/configuration-reference/#steps - steps: - # Checkout the code as the first step. - - checkout - # Use mvn clean and package as the standard maven build phase - - run: - name: Build - command: mvn -B -DskipTests clean package - # Then run your tests! - - run: - name: Test - command: mvn test jacoco:report coveralls:report -DsourceEncoding=UTF-8 -P ci - - deployment: - # These next lines define a Docker executor: https://circleci.com/docs/2.0/executor-types/ - # You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. - # Be sure to update the Docker image tag below to openjdk version of your application. - # A list of available CircleCI Docker Convenience Images are available here: https://circleci.com/developer/images/image/cimg/openjdk - docker: - - image: cimg/openjdk:17.0 - # Add steps to the job - # See: https://circleci.com/docs/2.0/configuration-reference/#steps - steps: - # Checkout the code as the first step. - - checkout - # Use mvn deploy as the standard maven build phase - - run: - name: Deploy - command: mvn deploy -Dmaven.test.skip -DcreateDocs=true -s settings.xml - # The resource_class feature allows configuring CPU and RAM resources for each job. Different resource classes are available for different executors. https://circleci.com/docs/2.0/configuration-reference/#resourceclass - resource_class: large - -# Invoke jobs via workflows -# See: https://circleci.com/docs/2.0/configuration-reference/#workflows -workflows: - build-test-deploy: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. - jobs: - - build-and-test - - deployment: - requires: - - build-and-test diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 93a98cfe5..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,12 +0,0 @@ -# These are supported funding model platforms - -github: [keilw] -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 2c5d35f54..000000000 --- a/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -/.settings -/.classpath -/.project -/.idea -/money-api.iml -/.resourceCache -/jdk-stub/bin -/target -/javamoney-api/core/bin -/javamoney-api/convert/bin -/javamoney-api/ext/bin -/javamoney-api/format/bin -/javamoney-api/singleton/bin -/money-impl/cdi/.settings/org.eclipse.wst.common.component -/money-impl/cdi/.settings/org.eclipse.wst.common.project.facet.core.xml -/money-impl/java-ee/.settings/org.eclipse.wst.common.component -/money-impl/java-ee/.settings/org.eclipse.wst.common.project.facet.core.xml -/money-impl/ri/.settings/org.eclipse.wst.common.project.facet.core.xml -/money-impl/ri/.settings/org.eclipse.wst.common.component -/money-platform/api/.settings/org.eclipse.wst.common.component -/money-platform/api/.settings/org.eclipse.wst.common.project.facet.core.xml -/money-api/platform/.settings -/money-platform/api/.settings/*.prefs -/money-platform/.settings -/money-platform/target -/doc - -tck-results \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 7a4a3ea24..000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) 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. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 40379e1f6..000000000 --- a/README.md +++ /dev/null @@ -1,29 +0,0 @@ -JSR 354: Money and Currency API -=============================== - -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/javax.money/money-api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/javax.money/money-api) -[![CircleCI](https://dl.circleci.com/status-badge/img/gh/JavaMoney/jsr354-api/tree/master.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/JavaMoney/jsr354-api/tree/master) -[![Coverage Status](https://coveralls.io/repos/JavaMoney/jsr354-api/badge.svg?branch=master)](https://coveralls.io/r/JavaMoney/jsr354-api?branch=master) -[![Stability: Maintenance](https://masterminds.github.io/stability/maintenance.svg)](https://masterminds.github.io/stability/maintenance.html) -[![Join the chat at https://gitter.im/JavaMoney/jsr354-api](https://img.shields.io/gitter/room/badges/shields.svg)](https://gitter.im/JavaMoney/jsr354-api?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -JSR 354 provides an API for representing, transporting, and performing comprehensive calculations with Money and Currency. -See the home page for more details: -http://jcp.org/en/jsr/detail?id=354 - -This is the API module of JSR 354 licenced under -- the Apache License Version 2.0 (LICENCE.txt) - -See also: -http://javamoney.github.io/ - -Release Notes -------------- - -- *1.0* API as defined by JSR 354 Spec. -- *1.0.1* API as defined by JSR 354 Spec (Fix: building Java 7 API with Java 7) -- *1.0.2* API as defined by JSR 354 Spec (Fix: built with Java 9) - dont use, use 1.0.3 instead! -- *1.0.3* API as defined by JSR 354 Spec (Compatible with Java 8, full Java 9 module support) -- *1.1* API as defined by JSR 354 MR 1. - -[![Built with Maven](http://maven.apache.org/images/logos/maven-feather.png)](http://maven.org/) diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 034e84803..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,21 +0,0 @@ -# Security Policy - -## Supported Versions - -Use this section to tell people about which versions of your project are -currently being supported with security updates. - -| Version | Supported | -| ------- | ------------------ | -| 5.1.x | :white_check_mark: | -| 5.0.x | :x: | -| 4.0.x | :white_check_mark: | -| < 4.0 | :x: | - -## Reporting a Vulnerability - -Use this section to tell people how to report a vulnerability. - -Tell them where to go, how often they can expect to get an update on a -reported vulnerability, what to expect if the vulnerability is accepted or -declined, etc. diff --git a/bnd.bnd b/bnd.bnd deleted file mode 100644 index 5111e4ff3..000000000 --- a/bnd.bnd +++ /dev/null @@ -1,26 +0,0 @@ -# Javac settings -javac.source: 1.8 -javac.target: 1.8 - -# Override automatic runtime requirement when building with JDK9+ -Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version>=8.0))" - --buildpath: \ - osgi.annotation; version=6.0.0,\ - osgi.core; version=6.0,\ - osgi.cmpn; version=6.0 - -Bundle-Version: ${project.version}.${tstamp} -Bundle-Name: JavaMoney API -Bundle-SymbolicName: javax.money -Bundle-Description: JavaMoney - API -Bundle-Category: Implementation -Bundle-Copyright: (C) Trivadis AG, Werner Keil, Otavio Santana -Bundle-License: Apache License 2.0 -Bundle-Vendor: Trivadis AG, Werner Keil, Otavio Santana -Bundle-DocURL: http://www.javamoney.org -Export-Package: \ - javax.money,\ - javax.money.spi,\ - javax.money.convert,\ - javax.money.format diff --git a/images/body-bg.png b/images/body-bg.png new file mode 100644 index 000000000..d0618fe74 Binary files /dev/null and b/images/body-bg.png differ diff --git a/images/highlight-bg.jpg b/images/highlight-bg.jpg new file mode 100644 index 000000000..4c4a78eff Binary files /dev/null and b/images/highlight-bg.jpg differ diff --git a/images/hr.png b/images/hr.png new file mode 100644 index 000000000..6c723a560 Binary files /dev/null and b/images/hr.png differ diff --git a/images/octocat-icon.png b/images/octocat-icon.png new file mode 100644 index 000000000..f0ba137d2 Binary files /dev/null and b/images/octocat-icon.png differ diff --git a/images/tar-gz-icon.png b/images/tar-gz-icon.png new file mode 100644 index 000000000..d50f34f6d Binary files /dev/null and b/images/tar-gz-icon.png differ diff --git a/images/zip-icon.png b/images/zip-icon.png new file mode 100644 index 000000000..162c425b4 Binary files /dev/null and b/images/zip-icon.png differ diff --git a/index.html b/index.html new file mode 100644 index 000000000..29fcd2347 --- /dev/null +++ b/index.html @@ -0,0 +1,62 @@ + + + + + + + + + + + Jsr354-api by JavaMoney + + + +
+
+ +
+

Jsr354-api

+

Money and Currency - JSR 354

+
+ +
+ Download .zip + Download .tar.gz + View on GitHub +
+ +
+ +
+

+Welcome to JSR 354 (API)

+ +

This project represents the source code modelling the API for JSR 354 Money & Currency: +Typically you will never work with this API standalone, instead of you would use an implementation dependency. Neverhtless this API is accessible by configuring the macen dependency:

+ +
<dependency>
+  <groupId>javax.money</groupId>
+  <artifactId>jsr354-api</artifactId>
+  <version>0.7</version>
+</dependency>
+
+ +

+Further information

+ +

For further information we recommend reading the specification document, located here (tbd)...

+
+ + + + +
+
+ + \ No newline at end of file diff --git a/javascripts/main.js b/javascripts/main.js new file mode 100644 index 000000000..d8135d37b --- /dev/null +++ b/javascripts/main.js @@ -0,0 +1 @@ +console.log('This would be the main JS file.'); diff --git a/params.json b/params.json new file mode 100644 index 000000000..c63519f62 --- /dev/null +++ b/params.json @@ -0,0 +1 @@ +{"name":"Jsr354-api","tagline":"Money and Currency - JSR 354","body":"### Welcome to JSR 354 (API)\r\nThis project represents the source code modelling the API for JSR 354 Money & Currency:\r\nTypically you will never work with this API standalone, instead of you would use an implementation dependency. Neverhtless this API is accessible by configuring the macen dependency:\r\n```\r\n\r\n javax.money\r\n jsr354-api\r\n 0.7\r\n\r\n```\r\n\r\n### Further information\r\nFor further information we recommend reading the specification document, located here (tbd)...\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 628dd74df..000000000 --- a/pom.xml +++ /dev/null @@ -1,1069 +0,0 @@ - - - - 4.0.0 - javax.money - money-api - jar - 1.1.1-SNAPSHOT - JSR 354 (Money and Currency API) - https://javamoney.github.io - 2012 - JSR 354 provides an API for representing, transporting, and performing comprehensive calculations with Money and Currency. - - - . - UTF-8 - UTF-8 - 1.8 - 9 - 9 - . - 2021 - - - 7.7.1 - 5.3.1 - 2.2 - 0.8.10 - 3.5.0 - 2.2.3 - 2.3.7 - true - - - - JSR 354 - Expert Group - http://javamoney.org - - - - - keilw - Werner Keil - - Maintenance Lead - - - - tom-huesler - Thomas Hüsler - Espalier Technologies - GMT+1 - - Expert Group Member - - - - otaviojava - Otávio Santana - - Maintenance Lead - - - - simasch - Simon Martinelli - - Expert Group Member - - - - chrisphe - Christopher Pheby - - Expert Group Member - - - - jeffprestes - Jefferson Prestes - - Expert Group Member - - - - jezdavies - Jeremy Davies - - Expert Group Member - - - - - - Manuela Grindei - - Expert Group Member - - - - - - Benjamin Cotton - - Expert Group Member - - - - jodastephen - Stephen Colebourne - - Expert Group Member - - - - - - Greg Bakos - - Expert Group Member - - - - - - Tony Jewell - - Expert Group Member - - - - rajmahendra - Rajmahendra Hegde - rajmahendra@gmail.com - JUG Chennai - - Expert Group Member - - - - - - Scott James - - Expert Group Member - - - - - - Matthias Buecker - - Expert Group Member - - - - - - Sanjay Nagpal - - Expert Group Member - - - - - - Mohamed Taman - - Expert Group Member - - - - crazybob - Bob Lee - - Expert Group Member - - - - - - Arumugam Swaminathan - - Expert Group Member - - - - - - Travis CI - https://travis-ci.org/JavaMoney/jsr354-api - - - - - JavaMoney @ groups.io - https://groups.io/g/javamoney/editsub - javamoney@groups.io - - - - - GitHub - https://github.com/JavaMoney/jsr354-api/issues - - - - - Apache License, Version 2.0 - LICENSE.txt - manual - - - - - 3.0.4 - - - - scm:git:https://github.com/JavaMoney/jsr354-api.git - master - scm:git:https://github.com/JavaMoney/jsr354-api.git - https://github.com/JavaMoney/jsr354-api - - - - - - - true - - ossrh-snapshot - OSSRH Snapshots - https://oss.sonatype.org/content/repositories/snapshots/ - - - - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - - ci - - - - - org.jacoco - jacoco-maven-plugin - - - org.eluder.coveralls - coveralls-maven-plugin - 4.3.0 - - - javax.xml.bind - jaxb-api - 2.2.3 - - - - ${env.COVERALLS_REPO_TOKEN} - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - release-sign-artifacts - - - performRelease - true - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.4 - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - - false - 11A1E4D6 - - - - sign-artifacts - verify - - sign - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - - - - - - - org.testng - testng - ${testng.version} - test - - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.hamcrest - hamcrest-library - ${hamcrest.version} - test - - - - - - - org.testng - testng - test - - - org.mockito - mockito-core - test - - - org.hamcrest - hamcrest-library - test - - - - - install - - - - org.apache.maven.wagon - wagon-ssh - 2.4 - - - org.apache.maven.wagon - wagon-webdav-jackrabbit - 2.2 - - - - - - - org.apache.maven.plugins - maven-site-plugin - 3.9.1 - - - - - - biz.aQute.bnd - bnd-maven-plugin - 3.5.0 - - - ch.qos.logback - logback-core - 1.2.10 - - - org.slf4j - slf4j-api - 1.7.13 - - - - - - bnd-process - - - - - - - org.apache.maven.plugins - maven-clean-plugin - 2.5 - - - org.apache.maven.plugins - maven-deploy-plugin - 2.7 - - - org.apache.maven.plugins - maven-resources-plugin - 2.6 - - - org.apache.maven.plugins - maven-jar-plugin - 3.0.2 - - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - - org.apache.maven.plugins - maven-war-plugin - 2.4 - - - org.apache.maven.plugins - maven-surefire-plugin - 2.15 - - false - false - once - true - - **/*Test.java - - - **/Abstract*.java - - ${closeTestReports} - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.0 - - ${maven.compiler.release} - ${maven.compiler.source} - ${maven.compiler.release} - - - - org.apache.maven.plugins - maven-assembly-plugin - 2.4 - - - org.apache.maven.plugins - maven-install-plugin - 2.4 - - - - install - - - true - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 2.8 - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${javadoc.version} - - java.money - java.money - -Xdoclint:none - false - true - false - false - 1.9 - false - - - - attach-javadocs - - jar - - - - - - maven-source-plugin - org.apache.maven.plugins - 2.2.1 - - - attach-sources - package - - jar-no-fork - - - - - - org.codehaus.mojo - versions-maven-plugin - 2.1 - - - org.asciidoctor - asciidoctor-maven-plugin - ${asciidoctor-maven.version} - - - org.jacoco - jacoco-maven-plugin - ${jacoco.version} - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.jacoco - - jacoco-maven-plugin - - - [0.8.2,) - - - prepare-agent - - - - - - - - - - - - - - com.mycila - license-maven-plugin - 3.0 - - - - check - - - - - - - - - org.jacoco - jacoco-maven-plugin - - - prepare-agent - - prepare-agent - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - - jar - - - - - - org.codehaus.mojo - versions-maven-plugin - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.0.0 - - - enforce-versions - - enforce - - - - - 3.0.4 - - - 1.7.0 - - - - true - true - true - - - - - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - true - - - ${project.name} - ${project.version} - Credit Suisse AG - ${project.organization.name} - http://www.javamoney.org - - - - - - org.asciidoctor - asciidoctor-maven-plugin - - - org.asciidoctor - asciidoctorj-pdf - ${asciidoctor-pdf.version} - - - - src/main/asciidoc - ${project.basedir} - src/main/asciidoc/images/ - true - - - - - output-html - prepare-package - - process-asciidoc - - - target/docs - coderay - html - - - - output-pdf - prepare-package - - process-asciidoc - - - pdf - - coderay - - - - - - - - - - - - - biz.aQute.bnd - bnd-maven-plugin - - - - bnd-process - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - default-compile - - - - - ${maven.compiler.release} - - - - - base-compile - - compile - - - - 8 - 8 - - module-info.java - - - - - - - - - - - com.mycila - license-maven-plugin - -
src/license/asl_2/header.txt
- - ${project.organization.name} - ${thisYear} - - - .editorconfig - .gitattributes - .github/** - .travis.yml - .circleci/** - **/LICENSE.txt - **/README.md - **/pom.xml - **/settings.xml - src/test/resources/** - src/main/resources/** - src/main/asciidoc/** - src/main/config/** - src/main/emf/** - src/site/** - src/asciidoc/** - src/license/** - *.css - *.jpg - *.png - *.yml - - - src/license/headers.xml - - - JAVA_STYLE - -
-
-
-
- - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${javadoc.version} - true - - - true - - aggregate - - - true - true - true - ${project.build.sourceCompilerLevel} - true - true - org.umlgraph.doclet.UmlGraphDoc - - org.umlgraph - umlgraph - 5.6 - - private - - -Xdoclint:none - -inferrel -inferdep -quiet -hide - java.* - -collpackages java.util.* - -postfixpackage -nodefontname - Tahoma - -nodefontsize 9 - -nodefontpackagesize 7 -outputencoding - UTF-8 - - - - - - - org.codehaus.mojo - jdepend-maven-plugin - 2.0 - - - org.apache.maven.plugins - maven-surefire-report-plugin - 3.0.0-M7 - - true - ${project.reporting.outputDirectory}/../xref-test - true - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.20.0 - - ${maven.compile.targetLevel} - xml - true - true - ${project.build.sourceEncoding} - - - - org.codehaus.mojo - taglist-maven-plugin - 3.0.0 - - true - ${project.build.sourceEncoding} - - - - Important fixes that have to be done until the - next - release - - - - FIXME - ignoreCase - - - - - Things to verify and to check - - - // check: - ignoreCase - - - - - Just things to do - - - todo - ignoreCase - - - @todo - ignoreCase - - - XXX - ignoreCase - - - - - - - - - org.apache.maven.plugins - maven-jxr-plugin - 3.0.0 - - true - true - true - ${project.name}/apidocs - - JSR 354 - Java Money API Sources - - - - org.apache.maven.plugins - maven-dependency-plugin - 2.8 - - - org.jacoco - jacoco-maven-plugin - ${jacoco.version} - - ${basedir}/target/coverage-reports/jacoco-unit.exec - ${basedir}/target/coverage-reports/jacoco-unit.exec - - - - - com.github.spotbugs - spotbugs-maven-plugin - 4.0.4 - - - org.apache.maven.plugins - maven-project-info-reports-plugin - 3.0.0 - - - - com.github.spotbugs - spotbugs-maven-plugin - 4.0.4 - - - org.apache.maven.plugins - maven-site-plugin - - - -
diff --git a/settings.xml b/settings.xml deleted file mode 100644 index ee39d7bab..000000000 --- a/settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - ossrh - ${env.CI_DEPLOY_USERNAME} - ${env.CI_DEPLOY_PASSWORD} - - - \ No newline at end of file diff --git a/src/license/asl_2/header.txt b/src/license/asl_2/header.txt deleted file mode 100644 index 146cdbe33..000000000 --- a/src/license/asl_2/header.txt +++ /dev/null @@ -1,14 +0,0 @@ -Copyright 2012-2016 Credit Suisse -Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file diff --git a/src/license/asl_2/license.txt b/src/license/asl_2/license.txt deleted file mode 100644 index 74f82e340..000000000 --- a/src/license/asl_2/license.txt +++ /dev/null @@ -1,16 +0,0 @@ -==== - Copyright 2012-2016 Credit Suisse - Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==== diff --git a/src/license/headers.xml b/src/license/headers.xml deleted file mode 100644 index 502e40bc4..000000000 --- a/src/license/headers.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - /* - * - */ - - - (\s|\t)*/\*.*$ - .*\*/(\s|\t)*$ - false - true - false - - diff --git a/src/license/licenses.properties b/src/license/licenses.properties deleted file mode 100644 index 462695305..000000000 --- a/src/license/licenses.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright 2012-2016 Credit Suisse -# Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -asl_2=Apache 2.0 License diff --git a/src/main/asciidoc/JavaMoneySpecification.adoc b/src/main/asciidoc/JavaMoneySpecification.adoc deleted file mode 100644 index 1c5253527..000000000 --- a/src/main/asciidoc/JavaMoneySpecification.adoc +++ /dev/null @@ -1,3255 +0,0 @@ -JSR 354 Money and Currency -- Specification -=========================================== -:title: JSR 354 (Money & Currency) - Specification -:revnumber: 1.1 -:revremark: Maintenance Release 1 -:revdate: May 2020 -:longversion: 1.1 (MR 1) May 2020 -:authorinitials: WKE, OGS, ATR -:author: Werner Keil; Otavio Santana; Anatole Tresch, Trivadis -:source-highlighter: coderay -:website: http://javamoney.org/ -:iconsdir: {imagesdir}/icons -:toc: -:toc-placement: manual -:icons: -:encoding: UTF-8 -:title: JSR 354 (Money & Currency) - Specification -:numbered: - -''' - -<<< - -image::https://raw.githubusercontent.com/JavaMoney/jsr354-api/master/src/main/asciidoc/images/javamoney_cup.jpg[] - -:numbered!: - -==== Version Information: ------------------------------------------------------------------- -Specification: JSR-354 Money and Currency API ("Specification") -Version: 1.1 -Status: Maintenance Release 1 -Release: May 2020 -Copyright: 2012-2016 - Credit Suisse AG - P.O.Box - 8070 Zurich - Switzerland - - 2018-2020 - Werner Keil, Otavio Santana, Trivadis AG - All rights reserved. ------------------------------------------------------------------- - -toc::[] - -<<< -:numbered: - -<<< - -== Introduction -This document is the specification of the Java API for Money and Currency. The technical objective is to provide a money -and currency API for Java, targeted at all users of currencies and monetary amounts, both simple but also expandable. -The API will provide support for standard [ISO-4217] and custom currencies, and a model for monetary amounts and -rounding. It will have extension points for adding additional features like currency exchange, financial calculations -and formulas. -Additionally, this JSR includes recommendations on interoperability and thread safety. - -=== Expert group -This work is being conducted as part of JSR 354 under the Java Community Process. This specification is the -result of the collaborative work of the members of the JSR 354 Expert Group and the community at large. The following -persons have actively contributed to Java Money in alphabetical order: - -* Greg Bakos -* Matthias Buecker (Credit Suisse) -* Stephen Colebourne -* Benjamin Cotton -* Jeremy Davies -* Manuela Grindei -* Thomas Huesler -* Scott James (Credit Suisse) -* Tony Jewell -* Werner Keil (Maintenance Lead) -* Bob Lee -* Simon Martinelli -* Sanjay Nagpal (Credit Suisse) -* Christopher Pheby -* Jefferson Prestes -* Arumugam Swaminathan -* Mohamed Taman -* Anatole Tresch (Trivadis, Maintenance Lead) -* Otávio Santana (Maintenance Lead) - -=== Specification goals -Monetary values are a key feature of many applications, yet the JDK provides little or no support. -The existing +java.util.Currency+ class is strictly a structure used for representing current <> currencies, -but not associated values or custom currencies. The JDK also provides no support for monetary arithmetic or currency -conversion, nor for a standard value type to represent a monetary amount. - -==== Specification Targets -JSR 354 targets to support all general application areas, e.g. - -* eCommerce -* Banking -* Finance & Investment -* Insurance and Pension -* ERP systems -* etc. - -This specification will not discuss low latency concerns as required for example by algorithmic trading applications. -Nevertheless the API was designed to support different implementations of monetary amounts and allows for extension in -several ways. So it should be flexible enough that corresponding implementations can be used transparently to -accommodate such applications. - -As it is the first Java LTS version and applications in the financial area will probably use Java 8 for several years this JSR supports -Java 8 as the minimum version. - -[[Scope]] -=== Scope -JSR 354 targets a standalone scope. Nevertheless we considered a later integration into the JDK, so its design and scope -must follow JDK patterns. Additionally the work on the JSR has shown, that it is possible to define a flexible -and comprehensive API that is compatible with Java 8, and also with Java SE Embedded. -Basically this affects usage of +java.math+ and +java.text+. Nevertheless the reference implementations are free to use -existing functionality and the JSR also includes requirements (also checkable by the TCK) to ensure a minimal set of -functionality on Java SE 8. -During the development of the JSR a wide set of features were implemented. Most of these features will not end up within -the JSR itself, enabling feature innovation elsewhere. The corresponding libraries were available under [JavaMoney] -as an Apache 2 licensed open source project. Though these libraries were removed from the JSR, their development -ensured that scope was fully evaluated and that the parts best suited to standardization were identified. - -=== Required Java version -The specification supports Java SE platforms version 8 and above. -The API is backward compatible with Java 8 while exposing a JPMS (Jigsaw) module for Java 9 and above, -so implementations may target any suitable Java SE version. -The reference implementation "Moneta" is modular and supports the Java Platform Module System (JPMS) as well as OSGi bundles, but it's binary compatible with Java 8 as the minimal Java version. - - -=== How this document is organized -There are five main sections in this document: - -* Use cases -* Requirements -* Specification -* Implementation Recommendations -* An appendix - -<<< - -[[UseCases]] -Use Cases --------- -This section describes some, but not all, of the use cases that should be covered with this JSR. - -=== Scenario eCommerce (Online-Shop) -One basic scenario that must be covered is a traditional web shop. Hereby products are presented and collected in a shopping cart. Each product can be added once or multiple times to the cart. Some sites also need to represent non integral amounts, such as 1.5 kg of a product. Additionally a site may be internationalized handling multiple currencies, perhaps controlled by user settings or address. -Summarizing this scenario implies the following requirements: - --> Prices for each item must be modeled by some monetary amount, representing a numeric amount in a single currency. - --> The prices for all items in the cart must be calculated, this requires sum up all monetary amounts. - --> The user may change the number of each items to purchase, either by defining an integral number (e.g. 2 products) or - a decimal point number (e.g. 1.5 kg). This requires multiplication with integer and decimal numbers. - --> Each item’s price must be presented to the customer with the required target currency and in the format expected. This - requires formatting of amounts and currencies according to the user’s Locale. - --> When changing the currency of a shopping cart, the catalog prices must be recalculated in the new target currency. - This requires accessing an exchange rate to be used and calculating the item amounts with the new currency by - performing _currency conversion_. - --> When a customer finally places an order, the total amount must be calculated, which may involve tax calculation. - This also requires multiplication of prices and flexible rounding to a bookable amount (depending on the target - currency). - --> Finally the amount to withdrawn from the credit card must be passed to a server system, that handles credit card - payments. This includes serialization of the amount and/or special formatting of the amount into the format - required by the remote server. - -[[TrradingScenario]] -=== Scenario Trading Site -On a financial trading system or a site displaying several financial information such as quotes, additional aspects must -be considered. Basically, since for real time data must be paid, often data is displayed that is so called deferred. -Customers may be able to create virtual portfolios with arbitrary instruments for simulation of investment strategies. -To estimate a possible investment historic charts and timelines are shown, which includes current, as well as -statistical data. Depending on the simulated investment also different precisions of the monetary amounts must be -possible. Finally also for evaluation of complex investment strategies or products very detailed arithmetic precision -may be required. -Summarizing this scenario implies the following requirements: - --> A monetary amount representing a stock quote or other financial instrument, may have arbitrary additional data - attached, such as mapped quote keys, the origin stock exchange, the accuracy of the of data (validity, current or - deferred), as well as the data’s provider. Additionally the internal logic typically requires that the data types - used, such as currencies and exchange rates, can be extended with additional data, that is specific to the concrete - use cases/implementation. - --> An exchange rate can be current, deferred or even historic and typically has a defined validity scope. - --> Legal requirements may restrict the information presented (e.g. the currencies available) to the user based on - several aspects: - ** geographic location of the client - ** legal aspects, such as the client’s contract - ** others - -This implies that access to financial data may be restricted based on several not predictable classifications that must -not match a country or locale. - -[[GameScenario]] -=== Scenario Virtual Worlds and Game Portals -Virtual worlds, e.g. online games, define their own game money (but also Facebook has its own money). User’s may obtain -such virtual money by paying some real amount, e.g. by credit card. This usage scenario implies the following -requirements: - --> It must be possible to model completely virtual currencies. Since virtual money also can be converted (paid) with - real money, the price effectively defines an exchange rate. - --> Since several virtual game portals exist, also the number of virtual currencies can not be foreseen. Additionally a - virtual world may even define different currencies (e.g. Bitcoin). - --> Since such exchange rates may change during time, historization must also be supported. - -[[SocialMarketsScenario]] -=== Scenario Social Markets -Within social markets things are exchanged using a completely virtual currency, which has no relation to any real -currency. It is used as an arbitrary measurement of something meaningful only to that social community. This usage -scenario implies the following requirements: - --> It must be possible to model virtual currencies that are able to completely replace any real currency schemes. - -[[FinanceScenario]] -=== Scenario Banking & Financial Applications -Applications in financial institutes, such as a bank or insurance companies must model monetary information in several -ways: exchange rates, interest rates, stock quotes, current as well as historic currencies must be supported. Typically -in such companies also internal systems exist that define additional schemas of financial data representation, e.g. for -historic currencies, exchange rates, risk analysis etc. Often such aspects can not be covered by the ISO 4217 currency -standard. As example imagine historic currencies, such as '“Deutsche Reichsmark”', gold nuggets or even completely other -things. -Additionally also within [ISO-4217] there are countries in Africa that share a common ISO code (e.g. +CFA+), but -nevertheless have different banknotes and coins per country. Also there are ambiguities that may be confusing, such as -+USD, USS, USN+, which all describe US dollars. -This usage scenario implies the following requirements: - --> Currencies as well as exchange rates must be historic, regional, and define their time validity range. - Currencies available may depend further from contract, current tenant or other aspects. The same may also be - +true+ for rounding algorithms. Access to these features must be very flexible and capable of behaving - different depending on the current runtime context. - --> Customized or legacy system in big financial institutions may define additional, arbitrary currency variants. - --> Such system may have additional data not covered by the JSR’s currency model, so it is important that the model will - be designed to be extensible. - --> Currencies of different type, must be mappable to each other. - -[[PensionScenario]] -=== Scenario Insurance & Pension -Complex calculation models are used within insurance and pension solutions, e.g. for scenario simulation and -forecasting. Different countries, companies or even investment strategies, have rather different models implemented, -that also may change quickly depending on legal changes. Such systems are built of several isolated building blocks of -different granularity size and complexity, starting from simple sum of amounts until to complex investment -strategy forecasts on an enterprise level. Such systems imply the following requirements: - --> Building blocks should be modeled/organized in a common repository and accessible by a common API, that also allows - introspection of the functionality available. This is a precondition so insurance solutions can reuse the blocks for - modeling the required business cases. - --> Input and Output data of calculations can be multivalued, e.g. for forecast scenarios, or statistical data. Hereby the - (value) types used can be completely different, such as numbers, amounts, currencies, strategy identifiers, dates, - time ranges, interest and exchange rates etc. So there must be a structure to model such compound data. - -<<< - -[[Requirements]] -Requirements ------------- -=== Core Requirements -Based on the scope and use cases described above the following core requirements can be identified: - -. The JSR must provide an API for handling and calculating with monetary amounts. -. The JSR must support different numeric capabilities and guarantees to be provided by the monetary amount - implementations. These data is called _monetary context_ and must be accessible from an amount instance during runtime. -. The JSR must specify a minimal set of interfaces for interoperability, since concrete usage scenarios do not allow to - define an implementation that is capable of covering all aspects identified. Consequently it must be possible that - implementations can provide several implementations for monetary amounts. -. The JSR must specify extension points for adding additional logic, e.g. for extending the arithmetic capabilities, - rounding, currencies, conversions, formats, statistics, filtering etc. -. Meta-data must be accessible using a generic API, so custom requirements can be implemented and context information - not explicitly defined by this JSR is accessible using a unified access mechanism. -. The API for monetary amounts must allow to externalize the numeric part of an amount to the most useful representation - on a runtime platform. Similarly it must be possible to create a new amount instance using an existing amount as a - template, hereby changing currency and/or numeric part as required. This ensures maximal portability and allows - externalization of complex financial calculations. -. The JSR must provide a minimal set of roundings. This should include basic roundings for ISO currencies, or roundings - defined by a monetary context. -. The JSR must also support arbitrary custom roundings. - -[[RequirementsFormatting]] -=== Formatting Requirements -It must be possible to format and parse monetary amounts. Therefore the JSR defines a +MonetaryAmountFormat+, which: - -. can format an amount into a String or into an +Appendable+. -. can parse an amount from a +CharSequence+ input. -. supports different formatting styles and placement strategies for the currency part. -. supports flexible number formatting similar to +java.text.DecimalFormat+. -. supports flexible grouping sizes and different grouping separators, e.g. 'Indian Rupees' can be formatted - correctly. footnote:[+java.text.NumberFormat+ only supports a fixed grouping size, e.g. 3. 'Indian Rupees' have - different grouping sizes applied, e.g. +INR 12,34,56,000.21+] -. supports rounding of amounts for display and reverse rounding during parsing. - -[[RequirementsFormattingEE]] -=== Java EE / Jakarta EE Support -. This JSR must avoid restrictions that prevents its use in different runtime environments, such as Java EE or Jakarta EE. Refer -also to the section <> for more details on possible EE/CDI integration. -Examples like <>, <>, <> or <> show a broad support for JSR 354 in the Java EE, Jakarta EE or Spring ecosystems. - -[[RequirementsNonFunctional]] -=== Non Functional Requirements -. Since this JSR may be a candidate to be included into the JDK later, any possible extension to the Java platform - must be fully backward compatible. -. Implementation requirements for currencies must require only minimal (if any) extensions on the existing - +java.util.Currency+. -. The JSR must be self-contained, meaning it must be possible to use the JSR, without acquiring of external resources, - e.g. accessing resources in the Internet. -. Interfaces defined should enable interoperability between different implementations, for data as well as - functional interoperability. The interfaces must cover all typical use cases, so casting to concrete types should not - be necessary normally. -. The API for monetary amounts must not expose its concrete numeric internal representation during compile time. -. Where feasible method naming and style for currency modeling should be in alignment with parts of the Java - Collection API or +java.time+ / <>: - .. same method name prefixes - +of()+ for all factories, unless their inheritance e.g. from +java.lang.Enum+ - - mandates otherwise, such as +valueOf()+. - .. basic creational factory methods with little/no conversion are named +of(...)+ - .. more complex factory methods, with some conversion, or requiring a specific name for clarity are named - +ofXxx(...)+ - .. factories that extract/convert from a broadly specified input (where there is a good chance of error) are named - +from(...)+ - .. parsing is explicitly named, as it is generally special, named +parse(...)+ - .. overall monetary API _feel_ should be similar to +java.math.BigDecimal+. -. Queries and contexts may require adding additional time related data, such as POSIX timestamps based on millisecond - resolution as returned by +System.currentTimeMillis()+ or other time types based on new Java 8 date/time API. - These aspects are not explicitly modeled, since they depend on the capabilities of the corresponding providers - and the <> capabilities provide good flexibility to implement these things effectively. -. This JSR will probably also be used also for (business) critical software like real time trading and similar systems. - These systems and use cases require very specific parameters, which are impossible to model by this JSR and - may vary for different use cases, provider and/or companies. As a solution attributable contexts and queries can be - passed optionally that can contain arbitrary parameters needed. -. Though performance aspects can not directly targeted by this JSR, it is important that the JSR considers performance - aspects where possible, so that provided implementations are able to optimize performance as required by the usage - scenarios they are targeting. - -[[Specification]] -Specification -------------- -=== Package and Project Structure -==== Package Overview -The JSR defines 4 packages: - -+javax.money+:: contains the main artifacts, such as +CurrencyUnit, MonetaryAmount, MonetaryContext, MonetaryOperator, -MonetaryQuery, MonetaryRounding+, and the singleton accessor +Monetary+. -It is discussed in section <>. The meta-data context and query features are discussed in <>. - -+javax.money.convert+:: contains the conversion artifacts +ExchangeRate, ExchangeRateProvider, CurrencyConversion+ -and the according +MonetaryConversions+ accessor singleton. It is discussed in section <>. - -+javax.money.format+:: contains the formatting artifacts +MonetaryAmountFormat, AmountFormatContext+ and the according -+MonetaryFormats+ accessor singleton. It is discussed in section <>. - -+javax.money.spi+:: contains the SPI interfaces provided by the JSR 354 API and the bootstrap logic, to support -different runtime environments and component loading mechanisms. It is discussed in section <>. - -[[Modules]] -==== Module/Repository Overview -The JSR’s source code repository under <> provides several modules: - -jsr354-api:: contains the JSR 354 API based on Java 8 as described by this specification. -jsr354-ri:: contains the ''Moneta'' reference implementation based on Java 8 language features. -jsr354-tck:: contains the technical compatibility kit (TCK). The TCK is built using Java 8. -javamoney-parent:: is a root “POM” project for all modules under +org.javamoney+. This includes the RI/TCK projects, - but not jsr354-api (which is standalone). - -The repository also contains additional modules such as - -javamoney-lib:: contains a set of financial libraries (JavaMoney) adding comprehensive support for extended - functionality, built on top of this JSR, but not part of the JSR. -javamoney-examples:: finally contains the examples and demos, and also is not part of this JSR. - - -[[CoreAPI]] -=== Money and Currency Core API -The package +javax.money+ contains the types representing currencies and monetary amounts, the core exceptions as well -as supporting types for rounding and the extensions API. Hereby the main artifacts are as follows: - -* +CurrencyUnit+ models the minimal properties of a currency. -* +MonetaryAmount+ defines what an amount's capabilities are. It provides interoperability between different - implementations on functional level. Interoperability on data level is ensured by +getNumber()+ and +getCurrency()+. - As a consequence amount can be implemented in different ways, focusing on the behavioural and data representation - requirements implied by the concrete use cases. -* The abstract type +NumberValue+ returns the numeric part of an amount, so it can be accessed and externalized in - different ways. Its purpose is to ensure maximal interoperability with existing functionality in the JDK. Therefore - it also extends +java.lang.Number+. -* +NumberSupplier+ and +CurrencySupplier+ model functional interfaces as defined by JDK 8. -* +MonetaryOperator+ and +MonetaryQuery+ model functional interfaces providing extension points for monetary logic. - They allow to implement external functionality, either adding operations returning an amount (+MonetaryOperator+), or - returning any arbitrary other value (+MonetaryQuery+). -* the +MonetaryAmountFactory+ finally represents an abstraction for creating new instances of amounts. Besides setting - an amount currency and number value, it allows also to change the numeric capabilities, if the underlying - implementation supports doing this. The capabilities available for a concrete factory can be queried by accessing - the 'default' and the 'maximal' +MonetaryContext+ -* +MonetaryContext+ models the meta-data of +MonetaryAmount+ instances, including a representation ot the numeric - capabilities of an instance as an immutable and platform independent type. -* +CurrencyContext+ models the meta-data of a +CurrencyUnit+ instance as an immutable and platform independent type. -* +RoundingContext+ models the meta-data of a +MonetaryRounding+ instance as an immutable and platform independent type. -* +MonetaryAmountFactoryQuery+ models a query for evaluating instances of +MonetatyAmountFactory+ given concrete - requirements/required capabilities. -* +CurrencyQuery+ models a query for evaluating instances of +CurrencyUnit+ given concrete - requirements/required capabilities. -* +RoundingQuery+ models a query for evaluating instances of +MonetaryRounding+ given concrete - requirements/required capabilities. -* +MonetaryContextBuilder, CurrencyContextBuilder, RoundingContextBuilder, MonetaryAmountFactoryQueryBuilder, - CurrencyQueryBuilder, RoundingQueryBuilder+ all model the builders necessary for creating instances of the several - context and query classes. -* +MonetaryException+ is the base exception class for the money API, it extends +java.lang.RuntimeException+. - -Finally the core module also contains base classes used for metadata and query modeling: - -* +AbstractContext+ models the abstract basic value type for additional context data, used in several parts of this - JSR. It provides the basic logic for implementing an immutable context internally using a +Map+ - store. -* +AbstractQuery+ models the abstract query value type for querying monetary data from the different singleton accessors - provided. +AbstractQuery+ extends +AbstractContext+. -* +AbstractContextBuilder, AbstractQueryBuilder+ model the abstract basic builder types for builders that create - instances of +AbstractContext, AbstractQuery+, used in several parts of this JSR. - -Refer to section <> for more details. - - -[NOTE] -======================================================================= -There are people that would argue, that concrete immutable value types should be used to model a monetary amount. -This topic was discussed intensively in the expert group, some of the aspects considered include: - -* Using a concrete type as the model for a monetary amount implies a strong coupling to a numeric representation. - Unfortunately, as seen in the use cases and requirements sections, performance and precision are conflicting - requirements. So modelling the amount as a concrete type would effectively prevent the flexibility that is required. -* Also using self-referencing template parameters was considered. The disadvantage is that you still have to know the - concrete class. In that case you could also use the concrete class directly, instead of using non trivial generics - semantics. Additionally in many cases these complex semantics would lead quite probably to broad usage of raw types, - which will make the design quite counterproductive. -* The interface based design gives maximum flexibility, ensures interoperability on data and operational - level and still does not prevent its use in high performance, low latency scenarios. -======================================================================= - -Nevertheless for an API to be complete, you need some type of concrete classes as entry points. Since the API is -designed as a standalone APIs the singleton accessor patterns are a good choice, so this API provides according -accessor classes. Summarizing the following singletons are available as part of the JSR's core module: - -* +Monetary+ - ** provides access and query functionality to +CurrencyUnit+ instances. - ** provides access and query functionality to factories for creating +MonetaryAmount+ instances. - ** provides access and query functionality to +MonetaryRounding+ instances. - -Additionally the conversion and formatting module also provide singletons: - -* +MonetaryConversions+ for accessing +CurrencyConversion+ and +ExchangeRateProvider+ instances. -* +MonetaryFormats+ for accessing +MonetaryAmountFormat+ instances. - -The following sections will describe these artifacts in more detail. - -[[CurrencyModel]] -==== Modeling of Currencies -When thinking of monetary values it is inevitable to think on how a currency must be modeled. Although the JDK already -provides a +java.util.Currency+ class, this JSR’s expert group discussed, if the existing abstraction is sufficient or -what kind of additions are necessary. - -Fortunately a minimal interface +CurrencyUnit+ could be extracted, that models almost a subset of the existing -functionality on +java.util.Currency+, so the existing class could easily implement the new interface. Compared to -+java.util.Currency+ the new currency interface does not provide methods for localizing a currency instance such as -+getDisplayName(Locale)+, +getSymbol(Locale)+. This allows to separate the different concerns of data modelling and -formatting. Additionally the JSR's currency interface provides access to a +CurrencyContext+ meta-data class, -which is capable of providing arbitrary meta-data on the current instance. This meta-data container can be used to -store additional data, such as the validity time range, corresponding regions or territories or provider data. - -So the +CurrencyUnit+ interface for currencies is modeled only with 4 methods as follows: - -[source,java] -.Interface CurrencyUnit --------------------------------------------- -public interface CurrencyUnit{ - String getCurrencyCode(); - int getNumericCode(); - int getDefaultFractionDigits(); - CurrencyContext getContext(); -} --------------------------------------------- - -Hereby - -* the method +getCurrencyCode()+ returns the unique currency code. Nevertheless since +CurrencyUnit+ also models non - ISO currencies, the semantics for other currency types may be different: For 'ISO' currencies this will the 3-letter - uppercase ISO code. For non ISO currencies no constraints are defined. -* the numeric code returned by +getNumericCode()+ is optional. If not defined it must be +-1+. In case of ISO - currencies the code must match the value of the corresponding ISO code. For alternate currency scheme, if - useful numeric code is defined for the currency, this code should be reflected accordingly. A numeric code - is defined to be unique within an underlying currency scheme, though the JSR dies only support accessing - currencies using their (unique) currency code. -* the default fraction digits define the typical scale of values with a given currency. -* the +CurrencyContext+ models additional metadata of a currency unit (refer to section <> for more - details on contexts). It basically allows to evaluate the data provider of a currency unit, but can also contain - additional data as useful, determined by the implementation that provided the currency instance. This context allows - to support also more complex use cases for extended currency meta-data such as: -** validity range, e.g. modeled as from/to +LocalDate+ -** regional validity constraints -** provider validity constraints, e.g. the target stock exchange -** internal provider reference ids -** conversion service URLs -** related customer or contract information -** etc. - -Furthermore implementations of +CurrencyUnit+ - -. must implement +equals/hashCode+, considering the concrete implementation type, currency code (which is defined to - be unique) and the +CurrencyContext+. -. must be comparable -. must be immutable and thread safe. -. must be serializable. - -[[AmountModel]] -==== Modeling of Monetary Amounts -Modeling of monetary amounts agnostic to its concrete numeric representation was one of the key design decisions. The -final design is intended to provide for implementors to handle very different use cases with distinct requirements. -This was necessary since it has shown that different usage scenarios of money can result in rather different -requirements to the numeric representation of amounts, which quite probably may not fit into a _one-fits-it-all_ -implementation. - -One key aspect is that a monetary amount must always be related to a currency. Mixing of currencies makes typically no -sense for arithmetic operations on amount or, even worse, results in useless and incorrect results. Properties and -operations of monetary amounts are modeled by an interface, called +javax.money.MonetaryAmount+. This enables -effective data and functional interoperability. In general the following aspects are modeled: - -* _Data interoperability_ allowing access to the amount’s - ** currency modeled as +CurrencyUnit+. - ** number value, for externalization, modeled as +NumberValue+. - ** accessing basic numeric state such as _negative, positive_ etc. - ** Methods for evaluating amount meta-data, such as _numeric capabilities_ of the concrete type (+MonetaryContext+). -* _Prototyping support_ for creating new +MonetaryAmount+ instances based on the same implementation, modeled by a - +MonetaryAmountFactory+, which is accessible from each instance calling +MonetaryAmount.getFactory()+. -* _Comparison methods_ for comparing two arbitrary amounts of the same currency, hereby comparing based on the - (effective) numeric value (e.g. ignoring trailing zeroes). -* _Basic arithmetic operations_ like addition, subtraction, division, multiplication. -* _Functional extension points_ modeled as +MonetaryOperator+ (returning amount instances of the same implementation type) - and +MonetaryQuery+ (returning any result type). - -The interface is defined as follows: - -[source,java] -.Interface MonetaryAmount --------------------------------------- -public interface MonetaryAmount{ - CurrencyUnit getCurrency(); - NumberValue getNumber(); - MonetaryContext getContext(); - - // Create a factory that allows to create a new amount based on this amount - MonetaryAmountFactory getFactory(); - - // Create an instance as a result of an external monetary operation - MonetaryAmount with(MonetaryOperator operator); - - // Query data from an amount - R query(MonetaryQuery query); - - // Comparison methods - boolean isGreaterThan(MonetaryAmount amount); - boolean isGreaterThanOrEqualsTo(MonetaryAmount amount); - boolean isLessThan(MonetaryAmount amount); - boolean isLessThanOrEqualsTo(MonetaryAmount amount); - ... - boolean isEqualTo(MonetaryAmount amount); - boolean isNegative(); - boolean isPositive(); - boolean isZero(); - int signum(); - - // Algorithmic functions and calculations - MonetaryAmount add(MonetaryAmount amount); - MonetaryAmount subtract(MonetaryAmount amount); - MonetaryAmount multiply(long amount); - MonetaryAmount multiply(double amount); - MonetaryAmount multiply(Number amount); - MonetaryAmount divide(long amount); - MonetaryAmount divide(double amount); - MonetaryAmount divide(Number amount); - MonetaryAmount remainder(long amount); - MonetaryAmount remainder(double amount); - MonetaryAmount remainder(Number amount); - MonetaryAmount divideAndRemainder(long amount); - MonetaryAmount divideAndRemainder(double amount); - MonetaryAmount divideAndRemainder(Number amount); - MonetaryAmount scaleByPowerOfTen(int power); - MonetaryAmount abs(); - MonetaryAmount negate(); - MonetaryAmount plus(); - MonetaryAmount stripTrailingZeros(); -} --------------------------------------- - -Hereby - -* +getCurrency()+ returns the amount’s currency, modeled as +CurrencyUnit+. Implementations may co-variantly change the - return type to a more specific implementation of +CurrencyUnit+ if desired. -* +NumberValue getNumber()+ returns a +NumberValue+ (discussed within the next section) that models the numeric part of - an amount for data interoperability. -* +getContext()+ allows to access the monetary meta-data context of an amount, which may include data similar - to +java.math.MathContext+ but also other arbitrary attributes determined by the implementation (refer to section - <> for more details on contexts). -* Instances of +MonetaryOperator+ and +MonetaryQuery+ can be applied on a +MonetaryAmount+ instance by passing them - to the +with(MonetaryOperator)+ or +query(MonetaryQuery)+ method. Whereas an operator calculates a new amount - based on a amount (an instance of an unary function), a query can return arbitrary result types. -* +isGreaterThan(MonetaryAmount), isLessThan(MonetaryAmount), isGreaterThanOrEqualTo(MonetaryAmount)+ etc. model basic - comparison methods, which are required to work also when comparing different implementation types. This is possible, - since the numeric representation as well as the +MonetaryContext+ can be accessed in a implementation agnostic way. - Also is important that the comparisons are based on the least significant numeric scale, e.g. +CHF 1.05+ and - +CHF 1.05000+ are considered to be 'equal'. -* The rest of the methods model common arithmetic operations that are often used in financial applications. Adding - and subtracting hereby is only possible with amounts that are of the same currency (aka being 'currency compatible' - footnote:[Note that currency conversion is a complex aspect that can not be performed implicitly or automatically. - E.g. a conversion rate is dependent from the target date and time, the currencies involved, the provider, the - amount ...]) with the amount, on which the operation is executed. The arithmetic methods should basically behave - similar to +java.math.BigDecimal+, always returning amounts with the same +CurrencyUnit+. -* The specification and interface do not define precisely how the amount is stored. Implementations could use a - +BigDecimal+, +long+ or something else. The only constraint is that the numeric value can be exposed as +NumberValue+ - and that the +MonetaryContext+ returned reflects the numeric capabilities accordingly. - -When dealing with +double+ values additional aspects must be considered: - -* multiplying/adding/subtracting with POSITIVE_INFINITY should throw ArithmeticException because it overflows -* multiplying/adding/subtracting with NEGATIVE_INFINITY should throw ArithmeticException because it overflows -* multiplying/adding/subtracting with NaN should throw ArithmeticException because the result is NaN -* dividing by POSITIVE_INFINITY returns 0 -* dividing by NEGATIVE_INFINITY returns 0 -* dividing/multiplying/adding/subtracting by NaN should throw ArithmeticException because the result is NaN - -Finally implementations of +MonetaryAmount+ - -. must implement +equals/hashCode+, hereby it is recommended considering - .. its implementation type - .. its +CurrencyUnit+ - .. its numeric value, with any _non significant trailing zeros truncated_. - .. its meta-data context, modeled as +MonetaryContext+ -. must be thread safe and immutable. -. must be comparable. -. should be serializable. -. should be final. -. Finally implementations should not implement a method +getAmount()+. This method is reserved for future integration - into the JDK. -. If the numeric representation allows to model +-0+, this value is also considered to be +isZero()==true+, and - additionally should be equal to +0+. -. This specification does no - further constrain the constructor or factory methods to be implemented, or the method signatures to be used. - -////////////////////////////////////////// -. To enable interoperability a method +public static T from(MonetaryAmount amount)+ is recommended to be implemented on - the concrete type, that allows conversion of a +MonetaryAmount+ to a concrete type +T+. -////////////////////////////////////////// - -NOTE: This also means that two different implementations types with the same currency and numeric value are 'NOT equal'. -For comparing two +MonetaryAmount+ instances during financial calculations the amount’s comparison methods should be -used. E.g. +isEqualTo(MonetaryAmount)+ must return +true+, if they have equal currencies and equal numeric values, -hereby ignoring non-significant trailing zeros and different monetary contexts. - -The interfaces +MonetaryOperator+ and +MonetaryQuery+ provide a powerful extension mechanism. The two interfaces -operate as a form of the strategy pattern, allowing the algorithm of a query or operation to be external to the -implementation of MonetaryAmount. Their design matches JSR-310 (date & time). - -[[NumberModel]] -==== Externalizing the Numeric Value of an Amount -In the previous section we have discussed the basic model of a monetary amount. For data interoperability between -different implementations it is very important that the numeric value of an amount can be effectively externalized. -This can be achieved by calling +NumberValue getNumber();+ on +MonetaryAmount+. - -Nevertheless simply returning +java.lang.Number+, is also not desired, since conversion to known types may imply -rounding errors or truncation. So +NumberValue+ extends +java.lang.Number+, which is the basic type used in -the JDK, but +NumberValue+ adds methods that help users to better identify the risks of different externalization -operations and provide functionality for effective access to the numeric data: - -[source,java] -.Abstract Class NumberValue -------------------------------------------------------------------------------- -public abstract class NumberValue extends java.lang.Number{ - public abstract Class getNumberType(); - public abstract int intValueExact(); - public abstract long longValueExact(); - public abstract double doubleValueExact(); - public abstract T numberValue(Class numberType); - public abstract T numberValueExact(Class numberType); - public abstract int getPrecision(); - public abstract int getScale(); - public abstract long getAmountFractionNumerator(); - public abstract long getAmountFractionDenominator(); -} -------------------------------------------------------------------------------- - -Hereby - -. +getNumberType()+ provides information about the numeric representation used internally. It explicitly does not - constrain the type returned to be a subtype of +java.lang.Number+ to allow alternate implementations to be used. -. +intValueExact(), longValueExact(), doubleValueExact()+ extend the methods defined in +java.lang.Number+, with their - exact variants. Exact means, that it is required to throw an +ArithmeticException+, if the current numeric value must - be truncated to fit into the required target type. So in the following cases an exception must be thrown: -.. the current amount's value exceeds the overall maximal value of the target type (overflow) -.. the current amount's fraction value cannot be mapped into the target type (underflow) -. the methods +getAmountFractionNumerator()+ and +getAmountFractionDenominator+ allow to extract the fraction part of an - amount in a flexible way. -. +numberValue(Class)+ allows accessing the numeric value hereby defining the required numeric representation type. - If needed the numeric value may be truncated to fit into the required type. The following types must be supported: -.. +Integer+ -.. +Long+ -.. +Float+ -.. +Double+ -.. If available in the current runtime environment also: +BigDecimal, BigInteger+ -. +numberValueExact(Class)+ works similarly to +numberValue(Class)+, but the value returned must be 'exact'. It is - required to throw an +ArithmeticException+, if the current numeric value must be truncated to fit into the required - target type. The types supported are similar to +numberValue(Class)+. -. +getPrecision(), getScale()+ allows to access the current precision and scale of the numeric value. - -[[ExtensionPointModel]] -==== Functional Extension Points: Operators and Queries -Since the model for monetary amounts only defines a minimal set of algorithmic functions and a prototyping mechanism -additional extension points are required to allow easily external functionality, e.g. more complex financial -operations, being applied on amounts. This is modeled by - -* +javax.money.MonetaryOperator+, which models a function +f(M1) -> M2+, that converts an amount to another amount, and -* +javax.money.MonetaryQuery+, which models a function +f(M1) -> T+, that converts an amount to any type of result. - -Functional interfaces are annotated with the +@FunctionalInterface+ annotation. - -[[MonetaryOperator]] -===== Monetary Operators -The interface +javax.money.MonetaryOperator+ defines an arbitrary function +f(M1) -> M2+, that converts an -amount to another amount. Examples of such operations are rounding, currency conversion or monetary calculations: - -[source,java] -.Interface MonetaryOperator -------------------------------------------------------------------------------- -@FunctionalInterface -public interface MonetaryOperator{ - MonetaryAmount apply(MonetaryAmount amount); -} -------------------------------------------------------------------------------- - -Monetary operators can be used to make any kind of change to the amount based on the original amount. For example, the -following requirements (not complete listing) would be covered: - -* rounding of amounts, see section <> -* currency conversion, see section <> -* financial calculations and formulas, see section <> -* other statistical use cases, e.g. by passing an operator to each element in a +Collection+ of +MonetaryAmount+ - or using the JDK 8 _Streaming API_. -* other monetary conversions - -Implementations of +MonetaryOperator+ are highly recommended to be - -. immutable and -. thread-safe - -A +MonetaryOperator+ is typically invoked on the instance of an +MonetaryAmount+, passing the operator as a parameter: - -[source,java] -.Example Usage of MonetaryOperator -------------------------------------------------------------------------------- -MonetaryAmount amount = ... -MonetaryOperator op = ... -MonetaryAmount result = amount.with(op); -------------------------------------------------------------------------------- - -Hereby, also looking at the signature of +MonetaryOperator+, the returned amount (implementation) type must be the same -as the amount type passed to the operator. This is also the case, when working with interfaces, so given the example -above the *following is required to apply always*: - -[source,java] -------------------------------------------------------------------------------- -MonetaryAmount amount = ... -MonetaryOperator op = ... -MonetaryAmount result = amount.with(op); - -assertTrue(amount.getClass()==result.getClass()) -------------------------------------------------------------------------------- - -Fortunately this can be achieved easily, since the same constraint applies similarly - -* to the type returned by the arithmetic operations on +MonetaryAmount+ <1>. -* the type returned by the +MonetaryAmountFactory+ accessible from each +MonetaryAmount+ <2>. - -So the following statements must also always apply: - -[source,java] -------------------------------------------------------------------------------- -<1> amount.getClass() == amount.multiply(2.5).getClass() -<2> amount.getClass() == amount.getFactory().with(2.5).create().getClass() -------------------------------------------------------------------------------- - -NOTE: The operator interface is equivalent to the +UnaryOperator+ interface, which is a functional interface -suitable for use with lambdas. - -[[MonetaryQuery]] -===== Monetary Queries -The interface +javax.money.MonetaryQuery+ models a function +f(M1) -> T+, that converts an amount to any type of result: - -[source,java] -.Interface MonetaryQuery -------------------------------------------------------------------------------- -@FunctionalInterface -public interface MonetaryQuery { - R queryFrom(MonetaryAmount amount); -} -------------------------------------------------------------------------------- - -Queries can be used to make any kind of query against the data held in the amount. For example, the following -requirements (not complete listing) would be covered: - -* Amount type conversion -* boolean queries (predicates), such as 'is negative', 'is zero' or 'is currency widely traded' -* splitting the amount into smaller amounts -* serialization to string/bytes, or other types -* accessing the amounts currency or properties in a functional way, additional to the supplier interfaces already - in place - -Implementations of +MonetaryQuery+ should be - -. immutable and -. thread-safe - -A +MonetaryQuery+ is typically invoked on an instance of +MonetaryAmount+, passing the query as a parameter: - -[source,java] -.Usage Example for s MonetaryQuery -------------------------------------------------------------------------------- -MonetaryAmount amount = ... -MonetaryQuery check4eyesPrincipleNeeded = ... -boolean is4eyesPrincipleNeeded = amount.query(check4eyesPrincipleNeeded); -------------------------------------------------------------------------------- - -NOTE: The query interface is equivalent to the +Function+ interface, which is a functional interface suitable -for use with Lambda expressions. - -[[MonetaryContext]] -==== The Monetary Context -The monetary context (+javax.money.MonetaryContext+) models the monetary amount's meta-data, including the numeric -capabilities (implementation) in a platform independent way (refer also to section <> for more -details on contexts). Though it has some similarities with +java.math.MathContext+ for +BigDecimal+ it is far more -flexible, since different implementations may add several attributes that be relevant. -A +MonetaryContext+ is basically used on the following distinct use cases: - -* It can be accessed on each instance of +MonetaryAmount+, hereby providing information about the numeric capabilities - of a concrete amount implementation instance without having to reference to the concrete implementation class. -* Instances of +MonetaryAmountFactory+ supports creation of +MonetaryAmount+ instances, hereby setting explicitly the - +MonetaryContext+ required. In such a case the factory uses this monetary context to determine the amount created. - +MonetaryAmountFactory.getDefaultMonetaryContext()+ returns the default context used. Similarly the maximal supported - capabilities of a +MonetaryAmountFactory+ can be determined by calling - +MonetaryAmountFactory.getMaximalMonetaryContext()+. Hereby the _maximal capabilities_ are determined: -** by the _maximal scale_, that an implementation type supports, without having to truncate any parts of the - numeric fraction -** by the _maximal precision_, that an implementation type supports, without having to truncate the whole or - the fractional part of an amount. -** basically additional aspects can be modeled as useful, but are not defined by this specification, e.g. the - +MonetaryContext+ can also contain an amount flavor or some other implementation priority, that can be used for - determining, which amount type is best suited for some use case. For additional aspects to be considered a - corresponding instance of +<>+ must be implemented and registered, with the - according component registration mechanism actually loaded by the JSR's +<>+ component. - -The +MonetaryContext+ is modeled as an immutable type as follows: - -[source,java] -.Class MonetaryContext -------------------------------------------------------------------------------- -public final class MonetaryContext extends AbstractContext -implements Serializable{ - ... - public int getPrecision(); - public int getMaxScale(); - public boolean isFixedScale(); - public Class getAmountType(); - public MonetaryContextBuilder toBuilder(); - -} -------------------------------------------------------------------------------- - -Hereby - - * +getPrecision(), getMaxScale(), isFixedScale()+ define common numeric capabilities. - * +getAmountType()+ gives access to the amount’s implementation type used. - * new instances are built using an instance of +MonetaryContextBuilder+, which also can be accessed from each - +MonetaryContext+ instance. - * the inherited +AbstractContext+ provides access to additional non standard context properties, see - <>. - -The example below creates a +MonetaryContext+ matching amount implementations that are performance optimized, that have -a maximal precision of +12+, with a maximal scale of +2+ and should be rounded up: - -[source,java] -.Class MonetaryContext -------------------------------------------------------------------------------- -enum MyFlavor{ // only an example, not part of the API - SLOW. FAST -} - -MonetaryContext ctx = MonetaryContextBuilder.of() - .setMaxScale(2) - .setFixedScale(true) - .setPrecision(12) - .set(RoundingMode.UP) - .set(MyFlavor.FAST) - .build(); -------------------------------------------------------------------------------- - -For further details on contexts, related builders and meta-data modeling, refer to section <>. - - -[[CreatingAmounts]] -==== Creating Monetary Amount Instances -Basically new instances of +MonetaryAmount+ can be created in different ways. One way footnote:[Types may also be -instantiated directly depending on the implementation.] will be by using factories, -modeled by the interface +javax.money.MonetaryAmountFactory+. Instances can be obtained in different ways - -* calling +getFactory()+ on an any instance of +MonetaryAmount+, returns an instance that is pre-initialized with the - current amount’s values, allowing for easily creation of similar amount instances, with some or multiple properties - changed. This is known as the prototype pattern [<>]. This is useful for +MonetaryOperator+ implementations, - where the default operations available on +MonetaryAmount+ are not sufficient for implementing the logic/result - required, or calculations are done externally and a new amount is created with the numeric result of that calculation. -* the +Monetary+ singleton also provides access to +MonetaryAmountFactory+ instances, hereby also allowing to - bind to a specific implementation type or query for matching +MonetaryAmountFactory+ instances: - -[source,java] -.Usage Example for creating an Amount, using an explicit type -------------------------------------------------------------------------------- -MonetaryAmountFactory fact = Monetary.getAmountFactory(MyMoney.class); -MyMoney money = fact.setCurrency("USD").setNumber(10.50).create(); -------------------------------------------------------------------------------- - -More complex evaluations of +MonetaryAmountFactory+ instances can be performed as only constraint by the registered -SPIs (see <>) using +MonetaryAmountFactoryQuery+ and its related Builder class: - -[source,java] -.Usage Example for querying for a +MonetaryAmountFactory+ -------------------------------------------------------------------------------- -MonetaryAmountFactory fact = Monetary.getAmountFactory( - MonetaryAmountFactoryQueryBuilder.of() - .setMaxScale(2) - .setPrecision(10) - .build()); -MonetaryAmount money = fact.setCurrency("USD").setNumber(10.50).create(); -------------------------------------------------------------------------------- - -As illustrated above the signature of +MonetaryAmountFactory+ is modeled as a builder also supporting a fluent -programming style: - -[source,java] -.Interface MonetaryAmountFactory -------------------------------------------------------------------------------- -public interface MonetaryAmountFactory { - Class getAmountType(); - MonetaryContext getDefaultMonetaryContext(); - MonetaryContext geMaximalMonetaryContext(); - - MonetaryAmountFactory setCurrency(CurrencyUnit currency); - MonetaryAmountFactory setNumber(double number); - MonetaryAmountFactory setNumber(long number); - MonetaryAmountFactory setNumber(Number number); - MonetaryAmountFactory setContext(MonetaryContext ctx); - MonetaryAmountFactory setCurrency(String code); - MonetaryAmountFactory setAmount(MonetaryAmount amount); - - T create(); -} -------------------------------------------------------------------------------- - -Hereby - -* create returns a new instance of +T+ based on the current properties of the factory instance. -* If no +MonetaryContext+ has been set explicitly a _default_ +MonetaryContext+ is used, which can be determined by - calling +getDefaultMonetaryContext()+. -* The _maximal_ supported +MonetaryContext+ can also be determined by calling +getMaximalMonetaryContext()+. -* +getAmountType()+ returns the amount implementation class that will be created by a given factory instance. -* +setAmount(MonetaryAmount)+ allow to initialize the factory with the values from any arbitrary amount. If the amount - passed hereby exceeds the maximal +MonetaryContext+ that can be supported, a +MonetaryException+ must be thrown. -* the other +setXXX+ methods allow to set other aspects of the +MonetaryAmount+ to be created, such as -** the +CurrencyUnit+ (either directly or by passing a currency code) -** the number value, hereby if a numeric value passed, that exceeds the representation capabilities of the targeted - amount implementation (or more precise: exceed the capabilities of the _maximal_ +MonetaryContext+), the following - strategy should be implemented: -*** If the current implementation supports extending the +MonetaryContext+ used, the +MonetaryContext+ should be - extended to accommodate the precision and scale required, e.g. an implementation based on +java.math.BigDecimal+ - can be constrained to a +MathContext.DECIMAL64+, but can be easily extended to support bigger precisions. -*** If the current implementation is not able to reflect the numeric value required without doing any significant - truncation, it must throw an +ArithmeticException+. - -[[SingletonAccessors]] -==== Accessing Currencies, Amounts and Roundings - -All JSR's main artifacts are accessible by corresponding singleton accessor classes. Hereby the exact behaviour of the -singletons are delegated to corresponding SPI's. This allows to implement runtime dependent behaviour that can be -different for different runtime environments, e.g. use CDI based contextual implementations, instead of the default -SE ServiceLoader based component lifecycle. Refer to section <> for more details. - -[[AccessingCurrencies]] -===== Accessing Currencies - -The +javax.money.Monetary+ singleton class implements an accessor for +CurrencyUnit+ instances. Each -implementation must also provide/include a provider that uses +java.util.Currency+ as a backend. But this JSR in -addition allows registration of additional currencies by implementing instances of -+CurrencyProviderSpi+ (refer to section <>): - -[source,java] -.Monetary Singleton (Currency related methods) -------------------------------------------------------------------------------- -public final class Monetary{ - private Monetary(){} - - public static CurrencyUnit getCurrency(String currencyCode, String... providers); - public static CurrencyUnit getCurrency(Locale locale, String... providers); - public static Set getCurrencies(Locale locale, String... providers); - public static boolean isCurrencyAvailable(String currencyCode, String... providers); - public static boolean isCurrencyAvailable(Locale locale, String... providers); - public static boolean isCurrencyAvailable(CurrencyQuery query); - public static Set getCurrencies(String... providers); - public static Collection getCurrencies(CurrencyQuery query); - public static Set getCurrencyProviderNames(); - public static List getDefaultCurrencyProviderChain(); - [...] -} -------------------------------------------------------------------------------- - -Hereby - -* access is provided based on +Locale+, or by using the currency code. Implementations must at least provide the same - locales and codes as supported by +java.util.Currency+. Additionally (compared to +java.util.Currency+) it is also - possible to access multiple currencies per +Locale+. -* additional +CurrencyUnit+ can be added by registering instances of the +CurrencyProviderSpi+ as explained within the - section <> later. -* whereas, similar to +java.util.Currency+ accessing a currency that does not exist, throws an - +IllegalArgumentException+, the +isCurrencyAvailable()+ methods allow to check if a currency code or +Locale+ is - defined, before accessing it. -* +getCurrencies(String...)+ allows to access all currencies currently known by this singleton (which delegates to - the known +<>+ instances). -* All access methods above also allow to pass an ellipse operator of provider names. If not set explicitly the - default providers and ordering as defined by +getDefaultProviderNames()+ must be used. Hereby - ** if only a single valued result is returned (+CurrencyUnit+, boolean), the provider chain is evaluated until - the first provider returns +true+ or a non-null +CurrencyUnit+ instance. - ** in case of multi valued results all values returned by the providers are added to the result collection - (+List, Set, Collection+). -* All available provider names are accessible from +getProviderNames()+. Hereby each provider name maps to exact one - instance of +CurrencyProviderSpi+. Refer to section <> for more details. -* The default provider names and ordering are accessible from +getDefaultProviderNames()+. -* Finally the method +getCurrencies(CurrencyQuery)+ gives you maximal flexibility for accessing currencies, e.g. - -[source,java] -.Example for querying currencies -------------------------------------------------------------------------------- -// Note: Enum Region only serves as an example and not part of the API -Collection currencies = Monetary.getCurrencies( - CurrencyQueryBuilder.of() - .setProvider("A", "B") - .set(Region.EMEA) - .set("contractNr", 12345) - .build() -); -------------------------------------------------------------------------------- - -The query interface also is flexible enough to support access to historic currencies. As an example, if an according -provider would be implemented and registered one could perform the following query: - -[source,java] -.Example for querying historic currencies -------------------------------------------------------------------------------- -// Note: This is just an example: no historic provider is part of the API or RI currently -Collection currencies = Monetary.getCurrencies( - CurrencyQueryBuilder.of() - .set(Locale.GERMANY) - .setTimestamp(LocalDate.of(1930,1,1)) - .build() -); -------------------------------------------------------------------------------- - -The default provider chain can be configured within the +javamoney.properties+ configuration file, located in the -classpath as follows: - -[source] -.javamoney.properties Configuration of default currencies provider chain -------------------------------------------------------------------------------- -# Defaults for java money -... -javax.money.defaults.Monetary.currencyProviderChain=provider1,provider2,provider3 -------------------------------------------------------------------------------- - -[[AccessingAmountFactories]] -===== Accessing Monetary Amount Factories - -The +javax.money.Monetary+ singleton class implements also an accessor for +MonetaryAmountFactory+ instances. Hereby -for not hard-coding the selection algorithm and for enabling contextual behaviour in a EE context, the singleton is -backed up by +<>+ and +<>+, that can be registered -using the JSR’s +<>+ mechanism. - -[source,java] -.Monetary Singleton (Amount Related Methods) -------------------------------------------------------------------------------- -public final class Monetary{ - private Monetary(){} - - public static MonetaryAmountFactory getAmountFactory(Class amountType); - public static MonetaryAmountFactory getDefaultAmountFactory(); - public static Collection> getAmountFactories(){ - public static Set> getAmountTypes(); - public static Class getDefaultAmountType(); - public static MonetaryAmountFactory getAmountFactory(MonetaryAmountFactoryQuery query); - public static Collection getAmountFactories(MonetaryAmountFactoryQuery query); - public static boolean isAvailable(MonetaryAmountFactoryQuery query); - [...] -} -------------------------------------------------------------------------------- - -Hereby - -* +getAmountFactory(Class)+ provides access to the corresponding MonetaryAmountFactory matching the amount type T. -* additionally a _default_ +MonetaryAmountFactory+ can be accessed, by calling +getDefaultAmountFactory()+. Hereby - the default type is the provided amount class of the +MonetaryAmountFactory+ with the highest priority (determined - by the Bootstrap implementation). This can be overridden by adding a +javamoney.properties+ file to the classpath - as follows: - -[source] -.javamoney.properties Configuration File -------------------------------------------------------------------------------- -# Defaults for java money - -javax.money.defaults.amount.class=my.fully.qualified.MonetaryAmountType -------------------------------------------------------------------------------- - -* +getAmountTypes()+ returns all amount implementation classes currently available. -* +getAmountFactories()+ returns all amount factories currently available. Compared to calling +getAmountTypes()+ the - factories provide also minimal and maximal monetary amount meta-data, which also includes corresponding - attributes describing the numeric capabilities supported. -* +getAmountFactory(MonetaryAmountFactoryQuery query)+ allow to access a +MonetaryAmountFactory+ that best covers the - given +MonetaryAmountFactoryQuery+. -* Finally +getAmountFactories(MonetaryAmountFactoryQuery query)+ allow to query multiple instances of - +MonetaryAmountFactory+ using a +MonetaryAmountFactoryQuery+. - -IMPORTANT: Implementations of this JSR must at least provide one implementation of -+MonetaryAmountFactoryProviderSpi+ with a query policy equal to -+MonetaryAmountFactoryProviderSpi.QueryInclusionPolicy.ALWAYS+*. Refer to section -<> for more details. - -[[AccessingRoundings]] -===== Accessing Roundings - -Rounding is modeled by implementations of +MonetaryRounding+, which extends +MonetaryOperator+ but also provides -rounding meta-data, modeled as +RoundingContext+. This is very useful since in the financial area beside mathematical -roundings, also non standard variants with arbitrary rules and constraints are quite common in the financial area. - -This JSR provides several roundings accessible from the +javax.money.Monetary+ singleton based on: - -. a target +CurrencyUnit+. By default the rounding is based on the currency’s default fraction units - (see +CurrencyUnit.getDefaultFractionDigits()+). -. an explicit (unique) _rounding id_ that must be known (and documented) by a +RoundingProviderSpi+ implementation. -. each implementation should at least enable accessing mathematical rounding, supporting -.. the maximal _precision_ (+int+) -.. the target _scale_ (+int+) -.. the +java.math.RoundingMode+, providing a definition of the required mathematical rounding. - If not defined +HALF_EVEN+ rounding mode should be used as a default. -. Using a +RoundingContext+, which can be configured with any kind of attributes. Also other use cases can be supported, - e.g. it could be possible to access special cash rounding, which may be different than the default currency rounding - (e.g. for +CHF/Swiss Francs+). - -The +Monetary+ singleton provides access to +MonetaryRounding+ instances as follows: - -[source,java] -.Monetary Singleton (Rounding related methods) -------------------------------------------------------------------------------- -public final class Monetary{ - private Monetary(){} - - public static MonetaryOperator getDefaultRounding(); - public static MonetaryRounding getRounding(CurrencyUnit currencyUnit, String... providers); - public static MonetaryRounding getRounding(String roundingName, String... providers); - public static MonetaryOperator getRounding(RoundingQuery query); - public static Collection getRoundings(RoundingQuery roundingQuery); - public static boolean isRoundingAvailable(String roundingName, String... providers); - public static boolean isRoundingAvailable(RoundingQuery query); - public static Set getRoundingNames(String... providers); - public static Set getRoundingProviderNames(); - public static List getDefaultRoundingProviderChain(); -} -------------------------------------------------------------------------------- - -Hereby - -* +getDefaultRounding()+ returns a general rounding instance that is dynamically implementing the default currency - rounding, as required by the currency passed, when called. -* +getRounding(CurrencyUnit, String...)+ returns the default rounding for the given +CurrencyUnit+. -* +getRounding(String, String...)+ returns an explicit named rounding. -* +getRoundingNames(String...)+ provides access to the rounding names of the currently registered roundings for - the given providers. -* +isRoundingAvailable+ allows to determine if the query function return corresponding roundings. -* All access methods above also allow to pass an ellipse operator of provider names. If not set explicitly the - default providers and ordering as defined by +getDefaultRoundingProviderNames()+ must be used. Hereby - ** if only a single valued result is returned (+MonetaryRounding+, boolean), the provider chain is evaluated until - the first provider returns +true+ or a non-null +CurrencyUnit+ instance. - ** in case of multi valued results all values returned by the providers are added to the result collection - (+List, Set, Collection+). -* +getRoundingProviderNames()+ provide the names of all currently registered +RoundingProviderSpi+ instances. Refer to section - <> for more details. -* +getDefaultRoundingProviderNames()+ provide the names of the current default +RoundingProviderSpi+ providers in the - corresponding chain order. -* +getRounding(RoundingQuery)+ offers maximal flexibility for accessing roundings. It is only restricted by the - capabilities provided by the registered +RoundingProviderSpi+ instances. Refer to section <> - for more details. -* +getRoundings(RoundingQuery)+ offers maximal flexibility for accessing roundings, but allows accessing multiple - roundings. - - -The +RoundingQuery+ for accessing a rounding from the +Monetary+ singleton is modeled as follows: - -[source,java] -.RoundingQuery Value Type -------------------------------------------------------------------------------- -public final class RoundingQuery extends AbstractQuery{ - ... - public String getRoundingName(); - public int getScale(); - public CurrencyUnit getCurrencyUnit(); - - public RoundingQueryBuilder toBuilder(); -} -------------------------------------------------------------------------------- - -By querying +MonetaryRounding+ instances with an instance of +RoundingQuery+ we can model easily some rather complex use -cases: - -. Access cash rounding for a +CurrencyUnit+, which may be different from the default rounding. - E.g. for +Swiss Francs+ the cash rounding will be in +5+ minor unit steps: +1.00, 1.05, 1.10+ etc. This can be - achieved by creating an instance of +RoundingContext+ with _currency unit_ and _cashRounding=true_ explicitly yet. -. Access to historic roundings can be achieved by setting a +CurrencyUnit+ and an (optional) target +LocalDate+ (or - whatever time type is most appropriate). -. by setting the _rounding id_ to a non default value, custom roundings can be implemented, e.g. for support - of technical formats. - -Instances of this value type can be created using an instance of +RoundingQueryBuilder+. So it would be possible (if -the registered provider supports this behaviour) to access special cash rounding, which may be different than the -default currency rounding (e.g. for +CHF/Swiss Francs+), as follows: - -[source,java] -.Example how a cash rounding could be accessed (not part of the API) -------------------------------------------------------------------------------- -LocalDate localDate = ...; -MonetaryRounding rounding = Monetary.getRounding( - RoundingQueryBuilder.of() <1> - .setRoundingName("cashRounding") <2> - .setCurrencyUnit("CHF") <3> - .set(localDate) <4> - .build()); <5> -------------------------------------------------------------------------------- -<1> Access a rounding by passing a +RoundingQuery+ -<2> Acquire a specific _named_ rounding. -<3> Set the target currency unit (predefined attribute). -<4> Access a rounding valid for the given +LocalDate+. -<5> Creates the new +RoundingQuery+ instance. - -Finally the default rounding provider chain can be configured within +javamoney.properties+ added to the classpath: - -[source] -.javamoney.properties Configuration of default currencies provider chain -------------------------------------------------------------------------------- -# Defaults for java money -... -javax.money.defaults.Monetary.roundingProviderChain=provider1,provider2,provider3 -------------------------------------------------------------------------------- - -[[FunctionalSupport]] -==== Additional Functional Support -Additionally to monetary operators and monetary queries access the the numeric -part as well as to the currency of an amount is modeled with corresponding _functional_ interfaces similarly. - -[[CurrencySupplier]] -===== CurrencySupplier -The interface +javax.money.CurrencySupplier+ is a functional interface similar to +Supplier+ as defined -in Java 8), whose functional method is +getCurrency()+: - -[source,java] -.Interface CurrencySupplier -------------------------------------------------------------------------------- -@FunctionalInterface -public interface CurrencySupplier { - CurrencyUnit getCurrency(); -} -------------------------------------------------------------------------------- - -Hereby - -* There is no requirement that a distinct result be returned each time the supplier is invoked. - -[[NumberSupplier]] -===== NumberSupplier -The interface +javax.money.NumberSupplier+ is a functional interface similar to specialization of -+Supplier+ as defined in Java 8), whose functional method is +getNumberValue()+: - -[source,java] -.Interface NumberSupplier -------------------------------------------------------------------------------- -@FunctionalInterface -public interface NumberSupplier { - NumberValue getNumber(); -} -------------------------------------------------------------------------------- - -Hereby - -* There is no requirement that a distinct result must be returned each time the supplier is invoked. - -[[Exceptions]] -==== Exception Types - -The core API defines basically two exception types: - -javax.money.MonetaryException:: -+javax.money.MonetaryException+ is a runtime exception, which models the base exception for all other exceptions. -Any monetary exception added by an implementation must inherit from this class. - -javax.money.UnknownCurrencyException:: -This runtime exception +extends MonetaryException+ and is thrown whenever -* a currency code given cannot be resolved into a corresponding +CurrencyUnit+ instance. The invalid currency code - passed is provided as a property on the exception as +public String getCurrencyCode();+. -* a +Locale+ given cannot be resolved into a corresponding +CurrencyUnit+ instance. The unresolvable +Locale+ passed is - provided as a property on the exception as +public Locale getLocale();+. - -[[CurrencyConversion]] -=== Currency Conversion -Currency conversion is an important aspect when dealing with monetary amounts. Unfortunately currency conversion has -a great variety of how it is implemented. Whereas a web shop may base its logic on an API provided by a financial -backend, that makes explicit conversion even not necessary, in the financial industry, conversion is a very complex -concern, since - -* conversion may be different based on the use case -* conversion may be different based on the provider of the exchange rates -* conversion rates may vary based on the amount to be converted -* conversion rates may vary based on contract or business unit -* conversion rates are different related to the target date/time - -Hereby this list is not complete. Different companies may have further requirements and aspects to be considered. -The API focuses on the common aspects of currency conversion such as: - -* a source and a target currency -* an exchange rate -* providing conversion providers and having the possibiity to address and combine providers as needed. - -Hereby currency conversion or the access of exchange rates can be parametrized with additional meta-data, similar -to other models defined by this JSR. This allows to enrich the basic model with whatever complexity is required, -hereby keeping the basic model as simple as possible. - -[[AccessingConversions]] -==== Accessing Monetary Conversions -Similar to other areas of this JSR a +MonetaryConversions+ singleoton is defined, which provides access to all different -aspects related to currency conversion, such as - -* access to providers that offer conversion rates, modeled as +<>+. -* access to conversion operators (+CurrencyConversion extends MonetaryOperator+), that can be used with any - +MonetaryAmount+ instances. -* access to further information about the providers currently available. - -The following sections give an overview about the functionality in more detail. Similar to other singletons also -+MonetaryConversions+ is backed up by a +MonetaryConversionsSingletonSpi+ SPI to allow customized (e.g. contextual) -implementation of the functionality defined. Refer to the <> section in this document for more details. - -==== Converting Amounts -Basically converting of amounts is modeled by the +CurrencyConversion+ interface which extends +MonetaryOperator+, -hereby adding meta-data support, modeled by +ConversionContext+. Hereby a *conversion is always bound to a specific -terminating (target) currency*. So basically a +MonetaryAmount+ can simply be converted by passing a -+CurrencyConversion+ to the amount's +with(MonetaryOperator)+ method: - -[source,java] -.Usage Sample Currency Conversion -------------------------------------------------------------------------------- -MonetaryAmount amount = ...; - -// Get a default conversion to Swiss Franc -CurrencyConversion conversion = MonetaryConversions.getConversion("CHF"); - -// Convert the amount -MonetaryAmount amount2 = amount.with(conversion); -------------------------------------------------------------------------------- - -Using a fluent API style this can be written even shorter as: - -[source,java] -------------------------------------------------------------------------------- -MonetaryAmount amount2 = amount.with(MonetaryConversions.getConversion("CHF")); -------------------------------------------------------------------------------- - -A +CurrencyConversion+ instance hereby also allows to extract the concrete +ExchangeRate+ applied. This allows -further pass the +ExchangeRate+ instance to any subsequent logic. - -[source,java] -.Currency Conversion, accessing exchange rates -------------------------------------------------------------------------------- -CurrencyConversion conversion = MonetaryConversions.getConversion("CHF"); -MonetaryAmount amount = ...; -ExchangeRate rate = conversion.getExchangeRate(amount); -------------------------------------------------------------------------------- - -Nevertheless for accessing +ExchangeRate+ instances an +ExchangeRateProvider+ is much more effective. It can be accessed -from the +MonetaryConversions+ singletons as well as from a +CurrencyConversion+. - -[[ExchangeRates]] -==== Exchange Rates and Rate Providers -===== Exchange Rates -The +ExchangeRate+ models the details of a conversion applied: - -* the base and terminating (target) +CurrencyUnit+. -* the conversion factor used footnote:[Note that the conversion rate can be dependent on the +MonetaryAmount+ passed.], - modeled as +NumberValue+. -* additional information if the rate is derived, meaning built up the result of rate chain. If a rate is derived - +getExchangeRateChain()+ returns the rate chain that is used to derive the given (final) exchange rate. -* a +ConversionContext+, which can contain arbitrary additional information about the provider that issued the rate and - arbitrary further aspects concerning the rate/conversion. - -Summarizing an +ExchangeRate+ is modeled as follows: - -[source,java] -.Interface ExchangeRate -------------------------------------------------------------------------------- -public interface ExchangeRate extends CurrencySupplier{ - ... - ConversionContext getContext(); - CurrencyUnit getBaseCurrency(); - CurrencyUnit getCurrency(); - NumberValue getFactor(); - // Support for chained rates - List getExchangeRateChain(); - boolean isDerived(); -} -------------------------------------------------------------------------------- - -Hereby - -* +getBaseCurrency(), getCurrency(), getFactor()+ model basically the mapping from the base currency to the target currency. -* +isDerived()+ allows to check if the mapping in fact is backed up by a derived mapping, e.g. a triangular rate chain. -* +getExchangeRateChain()+ return the full rate chain. In case of a non derived rate, this chain must contain only - the single rate itself. In case of triangular rate the chain contains all contained subrates. -* the +ConversionContext+ accessible from +getContext()+ allows to store additional meta data (refer also to - <> for further details) about the rate instance, such as - ** the rate's provider - ** the rate's +LocalDateTime+ or +ZonedDateTime+ - ** any other data that may be relevant -* each instance of rate finally can easily be converted into an according +ExchangeRate.Builder+ instance, so - adaptations/changes on existing rates can be done easily. - -Implementations of +ExchangeRate+ - -. must implement +equals/hashCode+, hereby it is recommended considering - .. its base and term +CurrencyUnit+ - .. its conversion factor - .. its +ConversionContext+ -. must be comparable. -. must be serializable. -. should be immutable and thread safe. -. should be implemented as value types, with a fluent Builder pattern. - -===== Exchange Rate Providers -We have seen in the previous section that an +ExchangeRate+ can be obtained from a +CurrencyConversion+ or from -its backing +ExchangeRateProvider+. Such a provider allows - -* to access +ExchangeRate+ instances, providing a base and a terminating (target) currency. -* to access +CurrencyConversion+ instances, providing a terminating (target) currency. - -Summarizing an +ExchangeRateProvider+ is modeled as follows: - -[source,java] -.Interface ExchangeRateProvider -------------------------------------------------------------------------------- -// Java 8 -public interface ExchangeRateProvider{ - ProviderContext getContext(); - - boolean isAvailable(ConversionQuery conversionQuery); - ExchangeRate getExchangeRate(ConversionQuery conversionQuery); - CurrencyConversion getCurrencyConversion(ConversionQuery conversionQuery); - - // modeled as default methods in Java 8 - boolean isAvailable(CurrencyUnit base, CurrencyUnit term); - boolean isAvailable(String baseCode, String termCode); - ExchangeRate getExchangeRate(CurrencyUnit base, CurrencyUnit term); - ExchangeRate getExchangeRate(String baseCode, String termCode); - CurrencyConversion getCurrencyConversion(CurrencyUnit term); - CurrencyConversion getCurrencyConversion(String termCode); - ExchangeRate getReversed(ExchangeRate rate); -} -------------------------------------------------------------------------------- - -Hereby - -* the +ProviderContext+ allows to provide additional provider meta-data, including the (required and unique) provider - name. -* the +isAvailable+ methods allow to check for availability of conversion rates from this a provider instance. -* the +getExchangeRate+ methods allow to access a concrete conversion rate. -* +getReversed+ can be called to reverse an exchange rate (NOTE: rates can, but must not be reversible). -* the +getCurrencyConversion+ methods allow to access a +CurrencyConversion+ that is internally backed up by the - given rate provider instance. - - -===== Conversion Query and Conversion Context -The API allows additionally to pass a +ConversionQuery+, which allow to pass any additional attributes/parameters -that may be required by a concrete +ExchangeRateProvider+ instance. This allows to support arbitrary complex use cases, -as an example footnote:[This example is completely arbitrary.] an implementation require/allow to pass - -* the target amount -* a customer id -* a contract id -* a fallback strategy -* a deferred rate should be obtained - -All these parameters then can be defined as part of a +ConversionQuery+. With such a query any kind of additional -parameters can be passed to the rate providers used to evaluate the required +ExchangeRate+. A +ConversionQuery+ then -can be used to parametrize the +<>+ as well as an +<>+ instance -acquired: - -[source,java] -.Usage Sample for configuring of a Currency Conversion / ExchangeRate (Provider) --------------------------------------------------------------------------- -ConversionQuery query = ConversionQueryBuilder.of() - .setRateType(RateType.DEFERRED). - .set("customerID", 1234) - .set("contractID", "213453-GFDT-02") - .set(FallbackStragey.PROVIDER) - .set(amount) - .setTermCurrency("CHF") - .build(); - -// Access a conversion... -CurrencyConversion conversion = MonetaryConversions.getConversion(query); - -// ... or access a rate provider. -ExchangeRateProvider prov = MonetaryConversions.getExchangeRateProvider(); -CurrencyConversion conversion = prov.getCurrencyConversion(query); - -// for a rate, we need also a base currency -query = query.toBuilder().setBaseCurrency("USD").build(); -ExchangeRate rate = prov.getExchangeRate(query); --------------------------------------------------------------------------- - -IMPORTANT: Important to understand is that its the responsibility of the used +ExchangeRateProvider+ implementation to -interpret the attributes passed within a +ConversionQuery+. Unknown parameters should simply be ignored, since a -provider can be used in a _provider chain_ (explained in the next section). - -[[ExchangeRateProviderChains]] -==== ExchangeRateProvider Chains -Reading the previous sections one might ask, how multiple providers can be used or how an individual rate provider can -be accessed. In fact all the examples seen so far rely on the default provider chain that can be accessed by calling -+MonetaryConversions.getDefaultProviderChain()+. Hereby the chain contains an ordered list of provider names, which -correspond to the provider names that identify each registered +ExchangeRateProvider+ uniquely. The provider name is -defined as a mandatory attribute on the +ProviderContext+, accessible from each +ExchangeRateProvider+ from -+ExchangeRateProvider.getContext()+. - -E.g. the output of the +European Central Bank (ECB)+ provider context, shipped with the _Moneta reference -implementation_, prints out the following when accessing +toString()+: - -[listing] --------------------------------------------------- -ProviderContext [attributes={PROVIDER=Compound: ECB}] --------------------------------------------------- - -[source,java] -.Usage Sample Accessing the default Exchange Rate Provider Chain IDs --------------------------------------------------------------------------- -// Accessing the default provider chain, configurable in javamoney.properties -List providerIds = MonetaryConversions.getDefaultProviderChain(); --------------------------------------------------------------------------- - -As mentioned accessing a currency conversion or rate provider, without passing the providers required returns the -default provider chain. So the following two statements are equivalent, given the default chain is +"ECB", "IMF", -"ECB-HIST"+: - -[source,java] -------------------------------------------------------------------------------- -// equivlent calls when the default provider chain equals to -// {"ECB", "IMF", "ECB-HIST"} -CurrencyConversion conversion = MonetaryConversions.getConversion("CHF"); -CurrencyConversion conversion = MonetaryConversions.getConversion("CHF", "ECB", "IMF", "ECB-HIST"); -------------------------------------------------------------------------------- - -Within a provider chain, the first provider that returns a non-null result determines the final value of the -method call, e.g. the exchange rate to be used to calculate the currency conversion. By passing the chain or providers -to be used different usage scenarios can be easily separated/supported, but still keeping the API simple for the -simple use cases. - -The default rate provider chain can be configured within +javamoney.properties+ added to the classpath: - -[source] -.javamoney.properties Configuration of default conversion provider chain -------------------------------------------------------------------------------- -# Defaults for java money -... -javax.money.defaults.MonetaryConversions.providerChain=provider1,provider2,provider3 -------------------------------------------------------------------------------- - -[[FormattingAPI]] -=== Money and Currency Formatting API -The formatting is modeled with a quite simple, but very flexible design. It allows the access of formats based -on +java.util.Locale+, similarly to the functionality in +java.text+, but offers flexibility that goes beyond the JDKs -formatting packages. In contrary to the JDK formatter the formatter defined by this API are thread-safe and -arbitrarily expandable. - -The entry point for the JSR formatter is the +MonetaryFormats+ singleton, which provides access to different formatter -API artifacts. The following section describes the relevant artifacts in more detail. - -==== Formatting of Monetary Amounts -As defined in <>, this JSR must provide an API for providing flexible and -expandable formatting capabilities for +MonetaryAmount+ instances. Though formatting is a very complex field the JSR’s -expert group has identified a minimal set of functionality, that provides an API simple to use, but still being -flexible to accommodate a wide range of usage scenarios. Aspects to be considered are: - -. Amount values can be rounded for display by applying any +MonetaryOperator+ before formatting/printing. -. Similarly amount values can be operated after parsing by applying any +MonetaryOperator+. This is the reciprocal - operation to the display rounding above. -. It is possible to define number grouping with flexible group sizes and different grouping characters. as for example - needed to format +INR+ footnote:[+INR 123456000.21+ is formatted as +INR 12,34,56,000.21+]. -. The currency part of an amount can be formatted in different ways: - .. as currency code, e.g. +USD+ - .. as numeric currency code, if such a code is defined. - .. as a (localized) currency symbol, e.g. +$+ - .. as a (localized) currency name, e.g. +Schweizer Franken+ - .. the currency part is omitted from the formatter's output (e.g. because its printed out somewhere else already). -. The overall formatting and parsing pattern can be defined similar to +java.text.DecimalFormat+, but also completely - different usage scenarios are possible. - -Fortunately all this scenarios can be covered by implementing instances of the +MonetaryAmountFormat+ interface as -shown below: - -[source,java] -.Interface MonetaryAmountFormat -------------------------------------------------------------------------------- -public interface MonetaryAmountFormat extends MonetaryQuery{ - String format(MonetaryAmount amount); - void print(Appendable appendable, MonetaryAmount amount) throws IOException; - MonetaryAmount parse(CharSequence text) throws ParseException; - AmountFormatContext getContext(); -} -------------------------------------------------------------------------------- - -Hereby - -* an amount can be formatted to a String or an +Appendable+, or parsed from a +String+. -* The meta-data of the format are provided by an immutable +AmountFormatContext+ value type. Refer to - <> for further details on meta-data modeling. - -The power of the API now comes with the capability to pass instances of +AmountFormatQuery+ to the singleton -for accessing +MonetaryAmountFormat+ instances. Similar to other queries defined by this JSR it is possible -to pass any additional parameters that are necessary to configure the concrete formatting to be returned. -Summarizing: -* The +AmountFormatQuery+ defines the parameters and attributes that configure a format. Hereby a format can be - identified by _name_ or configured on the fly. The effective behaviour depends on the concrete functionality - provided by the (possibly several) registered instances of type +<>+. -* The +<>+ implementation finally must interpret the attributes in - +AmountFormatContext+ and create an according formatter instance. - -With that simple approach, we can extend our formatting capabilities easily as needed. Nevertheless the basic API for -common use cases still is simple, since we can also access formatting just using a +Locale+, similarly to -+javax.text.DecimalFormat.getCurrencyInstance(Locale)+. - -IMPORTANT: Implementations of this JSR must provide according default formatter for each +Locale+ that is also -available from +javax.text.DecimalFormat.getCurrencyInstance(Locale)+. Hereby it is not required that the format -is exact the same, e.g. formatting for Indian Rupees is expected to have different grouping sizes. - -Contrary to the formatter in +javax.text+ implementations of this interface must be thread-safe. - -Examples:: -Given the API above, acquiring a +MonetaryAmountFormat+ instance is simple, the most simple usage is just accessing one -using a +Locale+: - -[source,java] -.Usage Example Formatting a MonetaryAmount --------------------------------------------------------------------------- -MonetaryAmountFactory f = Monetary.getDefaultAmountFactory(); -MonetaryAmount amount = f.setCurrency("CHF").setNumber(12.50).create(); - -MonetaryAmountFormat format = - MonetaryFormats.getAmountFormat(Locale.GERMANY); - -// format the given amount -String formatted = format.format(amount); // result: CHF 12,50 - -// create another amount based on the given amount -amount = f.toBuilder().setCurrency("INR").setNumber(123456789101112.123456).create(); -formatted = format.format(amount); // result: INR 123.456.789.101.112,12 --------------------------------------------------------------------------- - -For Indian Rupees (+INR+) it would be, of course, better using the Indian number format and different grouping sizes, -for this we could configure an +AmountFormatContext+ that implements this behaviour as illustrated below: - -[source,java] -.Usage Example (continued) Formatting a MonetaryAmount --------------------------------------------------------------------------- -AmountFormatQuery query = AmountFormatQueryBuilder.of(new Locale("","INR")) - .set("groupSizes", new int[]{3,2]).build(); -MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(query); - -MonetaryAmount amount = - Monetary.getDefaultAmountFactory() - .setCurrency("INR") - .setNumber(123456789101112.123456).create(); - -String formatted = format.format(amount); - // result: INR 12,34,56,78,91,01,112.12 --------------------------------------------------------------------------- - -[[ConfigureFormatting]] -==== Configuring a Monetary Amount Formatter -As mentioned before a +MonetaryAmountFormat+ can be configured using an +AmountFormatQuery+ with arbitrary -attributes, so also very complex and historic formats can be supported easily. Instances of +AmountFormatQuery+ can be -created using an +AmountFormatQueryBuilder+: - -[source,java] -.Class AmountFormatQuery -------------------------------------------------------------------------------- -public final class AmountFormatQuery extends AbstractQuery{ - private AmountFormatQuery(AmountFormatQueryBuilder builder); - ... - public String getFormatName(); - public Locale getLocale(); - public AmountFormatQueryBuilder toBuilder(); - -} - -public final class AmountFormatQueryBuilder extends AbstractQueryBuilder{ - ... - public static AmountFormatQueryBuilder create(String formatName); - public static AmountFormatQueryBuilder create(Locale locale); - - public AmountFormatQueryBuilder setMonetaryQuery(MonetaryQuery monetaryQuery); - - public AmountFormatQuery build(); - -} -------------------------------------------------------------------------------- - -Hereby the above listing illustrates quite well, what are the minimal properties that define an +AmountFormatQuery+: - -* a format name, by default +"default"+. -* a +Locale+ -* of course, additional parameters can be added as needed, such as output and input patterns, color or style settings, - +MonetaryAmountFactory+ instance to be used for creating amounts on parsing etc. - -The configuration active for a concrete +MonetaryAmountFormat+ is accessible also from the +AmountFormatContext+, which -can obtained by calling +MonetaryAmountFormat.getContext()+. - - -[[AccessingFormats]] -==== MonetaryFormats Accessor Singleton -The class +javax.money.format.MonetaryFormats+ models a singleton accessor, which is, similarly to other singleton in -this JSR, backed up by an SPI instance of +<>+. The SPI implementation is -responsible for collecting and managing registered instances of +MonetaryAmountFormatProviderSpi+ providing them based -on the +AmountFormatQuery+ passed. Such a query can contain - -* a +Locale+, or -* a format name -* the target providers that should be selected to handle the query to create/provide a +MonetaryAmountFormat+ instance. -* any other attributes as defined by the provider that should handle the query, refer to the section - <> for more details. - -[source,java] -.Interface MonetaryFormatsSingletonSpi -------------------------------------------------------------------------------- -public interface MonetaryFormatsSingletonSpi{ - Collection getAmountFormats(AmountFormatQuery query); <1> - Set getAvailableLocales(String... providers); <2> - Set getFormatNames(String... providers); <3> - Set getProviderNames(); <4> - List geDefaultProviderChain(); <5> - - // The following methods are modeled as default methods in Java 8 - MonetaryAmountFormat getAmountFormat(Locale locale, String... providers){...} <6> - MonetaryAmountFormat getAmountFormat(Locale locale, String... providers){...} <6> - MonetaryAmountFormat getAmountFormat(String name, String... providers); <6> - boolean isAvailable(Locale locale, String... providers){...} <7> - boolean isAvailable(AmountFormatQuery formatQuery){...} <7> - -} -------------------------------------------------------------------------------- -<1> Main method called for accessing formats. -<2> Collect all locales available from the given providers. If no provider IDs are passed the default provider chain - is used. -<3> Get the available format names for the given providers. If no provider IDs are passed the default provider chain - is used. -<4> Access all registered provider's ids. -<5> Access the ids of the default provider chain, in the ordering as executing. -<6> In java 8 these methods are provided as default methods delegating to +getAmountFormats(AmountFormatQuery)+. -<7> In java 8 these methods are default methods trying to access a formatting calling - +getAmountFormats(AmountFormatQuery)+. - - -Similar to other singletons of this JSR overriding the -+<>+ allows to add contextual behaviour in EE or multi-tenancy runtime environment. -Refer to <> for further details. - -The +MonetaryFormats+ singleton finally defines the following access methods, very similar to the -+MonetaryFOrmatsSingletonSpi+: - -[source,java] -.MonetaryFormats Singleton -------------------------------------------------------------------------------- -public final class MonetaryFormats{ - private MonetaryFormats(){} - - public static MonetaryAmountFormat getAmountFormat(Locale locale); - public static MonetaryAmountFormat getAmountFormat(AmountFormatContext context); - public static MonetaryAmountFormat getAmountFormat(Locale locale, String... providers){...} - public static MonetaryAmountFormat getAmountFormat(Locale locale, String... providers){...} - public static MonetaryAmountFormat getAmountFormat(String name, String... providers); - public static Collection getAmountFormats(AmountFormatQuery query); - public static boolean isAvailable(Locale locale, String... providers){...} - public static boolean isAvailable(AmountFormatQuery formatQuery){...} - public static Set getAvailableLocales(String... providers); - public static Set getFormatNames(String... providers); - public static Set getFormatProviderNames(); - public static List geDefaultFormatProviderChain(); -} -------------------------------------------------------------------------------- - -The design chosen ist so flexible that every kind of formatting related to monetary amounts can be easily mapped. -The code below illustrates a hypothetical, but more complex example: - -[source,java] -.Advanced setup of a AmountFormatQuery -------------------------------------------------------------------------------- -AmountFormatQuery query = new AmountFormatQueryBuilder.of("htmlFormat")<1> - .set("title", "MyTitle") <2> - .set("negativeStyle", ".negNumber") <3> - .set("positiveStyle", ".posNumber+) <3> - .set("styleClass", "styledAmount") <4> - .build(); <5> -------------------------------------------------------------------------------- -<1> Access a format with name +htmlFormat+ -<2> Sets the format's display name -<3> Sets the CSS style classes to be used for positive and negative values. -<4> Sets the overall default style class. -<5> Creates a new instance. - -NOTE: The example above is arbitrarily chosen. This specification does not require this behaviour to be available, or -be implemented as shown before. - -Similar to currency conversion the default format provider chain can be configured within +javamoney.properties+ added -to the classpath: - -[source] -.javamoney.properties Configuration of default format provider chain -------------------------------------------------------------------------------- -# Defaults for java money -... -javax.money.defaults.MonetaryFormats.providerChain=provider1,provider2,provider3 -------------------------------------------------------------------------------- - -==== Formatting Exceptions -javax.money.format.MonetaryParseException:: -This runtime exception +extends MonetaryException+ and is thrown whenever a +MonetaryAmount+ could not be parsed -successfully. It provides hereby additional info: - -* the original input +CharSequence+ passed to the +MonetaryAmountFormat+. -* the error index within the input String, where parsing failed unrecoverable. - - -[[SPI]] -=== Money and Currency SPI -JSR 354 defines a complete API and provides a default reference implementation. An implementation of this API must -provide several implementation services, called the SPI, to provide the effective functionality. These services must be -registered to the JSR's +Bootstrap+ mechanism. The +Bootstrap+ singleton internally loads an instance of -+ServiceProvider+ using +java.util.ServiceLoader+. The default loader used hereby relies on -+java.util.ServiceLoader+ to load the implementation services, so be default the JSR behaves like a normal SE -based JSR. However by registering alternate implementations of +ServiceProvider+ the component loading mechanism can -be replaced completely, e.g. with a mechanism that also tries to get access a _CDI_ +BeanManager+ from JNDI -thus enabling to register SPI implementations as CDI managed beans. - -All SPIs are contained in the package +javax.money.spi+. Summarizing the following SPIs are available: - -.Core SPI - -* +CurrencyProviderSpi+ (mandatory, multiple service chain) - provides instances of +CurrencyUnit+, accessible from - +Monetary+ singleton. -* +MonetaryAmountsSingletonSpi+ (mandatory, only one instance selected by priority) - manages instances of - +MonetaryAmountFactoryProviderSpi+, which create instances of +MonetaryAmountFactory+, that are being accessible from - the +Monetary+ singleton. -* +MonetaryAmountFactoryProviderSpi+ (mandatory, multiple service chain) - is responsible for registering and providing - instances of +MonetaryAmountFactory+. -* +MonetaryAmountsSingletonQuerySpi+ (mandatory, only one instance selected by priority) - this SPI allows to - override/define the behaviour of +Monetary.queryAmountType(MonetaryContext)+. -* +RoundingProviderSpi+ (mandatory, multiple service chain) - provides instances of +MonetaryOperator+, for being - accessible from +Monetary+. -* +MonetaryRoundingsSingletonSpi+ controls the loading of +RoundingProviderSpi+ instances. - - -.Conversion SPI - -* +MonetaryConversionSingletonSpi+ (mandatory, only one instance selected by priority) - manages instances of - +ExchangeRateProvider+, for being accessible by the +Monetary+ singleton and also is responsible for - providing the composite provider instances as to be returned by the conversion API. -* +ExchangeRateProvider+ (mandatory, multiple instances selected by API) - this class is also part of the API, but also - models the huge part of the SPI required for currency conversion. - - -.Formatting SPI - -* +MonetaryAmountFormatSingletonSpi+ (mandatory, only one instance selected by priority) - provides the backing bean for - the +MonetaryFormats+ singleton, manages instances of +MonetaryAmountFormatProviderSpi+. -* +MonetaryAmountFormatProviderSpi+ (mandatory, multiple service chain) - provides instances of +MonetaryAmountFormat+, - for being accessible by+ MonetaryFormats.getAmountFormat()+. - - -.Bootstrap SPI - -* +ServiceProvider+ (optional, only one instance selected by priority), defines the singleton accessor for loading SPI - components used by the +Bootstrap+ class. -* How the implementations must be registered depends on the +ServiceProvider+ that is loaded by the +Bootstrap+ - implementation. The default mechanism is based on the +java.util.ServiceLoader+ class. By ordering the registered - instances of some type along the priority (the most significant first), it is also possible to override partial - aspects, as the first a _non null_ result returned by a provider is taken as result of a call. The prioritization of - components is implicitly defined by the order of the components returned by the +ServiceProvider+ SPI implementation. - -NOTE: SPI interfaces called +XXXSingletonSpi+ are generally loaded once during early boot of the JSR and are subsequently -managed as static references within the singleton accessors. This may look as a constraint, but in fact you just have -to ensure to delegate component loading and management to the +Bootstrap+ mechanism. You can refer to the Moneta -reference implementation for further details, which exactly implements this behaviour. - - -[[CoreSPI]] -==== Core SPI -===== Accessing Currencies -Currencies are accessed from the <> singleton. This singleton is backed up by an implementation of -+MonetaryCurrenciesSingletonSpi+, which must be registered to the <>: - - -[source,java] -.Interface MonetaryCurrenciesSingletonSpi -------------------------------------------------------------------------------- -public interface MonetaryCurrenciesSingletonSpi { - List getDefaultProviderChain(); - Set getProviderNames(); - Set getCurrencies(CurrencyQuery query); - - // The following methods are modeled as default methods in Java 8 - CurrencyUnit getCurrency(String currencyCode, String... providers); - CurrencyUnit getCurrency(Locale country, String... providers); - Set getCurrencies(Locale locale, String... providers); - boolean isCurrencyAvailable(String code, String... providers); - boolean isCurrencyAvailable(Locale locale, String... providers); - Set getCurrencies(String... providers); - CurrencyUnit getCurrency(CurrencyQuery query); -} -------------------------------------------------------------------------------- - -Hereby - -* Similar to other areas multiple instances of +CurrencyProviderSpi+ can be registered. -* Each +CurrencyProviderSpi+ instance is identified by its (unique) provider name. -* On access the required chain of +CurrencyProviderSpi+ can be defined explicitly. -* If no provider chain is explicitly passed, the default provider chain as defined by +getDefaultProviderChain()+ - is used. -* When accessing +CurrencyUnit+ instances the first non null/not empty instances returned by a provider are used - as a result by default. Implementations of +MonetaryCurrenciesSingletonSpi+ may also add additional combination - strategies by defining additional attributes that can be passed as part of a +CurrencyQuery+ passed. -* Basically it is sufficient for implementations to provide the +getCurrencies(CurrencyQuery)+ method for looking - up currencies, since by default all other methods delegate to this method. - -Implementations of this class should use the <> suport to evaluate the instances of +CurrencyProviderSpi+ -for a given runtime context. - - -===== Registering Currencies -By registering instances of +javax.money.spi.CurrencyProviderSpi+ to the <> logic additional +CurrencyUnit+ -instances can be registered into the +Monetary+ singleton: - -[source,java] -.Interface CurrencyProviderSpi -------------------------------------------------------------------------------- -public interface CurrencyProviderSpi { - Set getCurrencies(CurrencyQuery query); - - // Modelled as default methods in Java 8 - String getProviderName(); - boolean isCurrencyAvailable(CurrencyQuery query); -} -------------------------------------------------------------------------------- - -Hereby - -* each provider must return a unique provider ID from +getProviderName()+. By - default the provider's simple class name is used. -* with +getCurrencies(CurrencyQuery)+ each provider can return the +CurrencyUnit+ instances that are valid as - defined by the +CurrencyQuery+ instance passed. Hereby a query can refer to a single currency instance, or a more - open query returning multiple instances. Additional parameters can be supported as needed for the concrete - use cases, e.g. historic or regional reference, namespace schemas etc. If a provider cannot deliver any +CurrencyUnit+ - instances, an empty +Set+ must be returned. -* +isCurrencyAvailable(CurrencyQuery)+ allows to check for any currencies being available. By default this method - calls +getCurrencies(CurrencyQuery)+ and simply checks for an empty +Set+ being returned. Implementations may - override this behaviour with a more efficient approach. - - -===== Registering Monetary Amount Factories -The +javax.money.spi.MonetaryAmountFactoryProviderSpi+ interface allows to create new instances of -+MonetaryAmountFactory+. The signature looks as follows: - -[source,java] -.Interface MonetaryAmountFactoryProviderSpi -------------------------------------------------------------------------------- -public interface MonetaryAmountFactoryProviderSpi { - public static enum QueryInclusionPolicy { - ALWAYS, - DIRECT_REFERENCE_ONLY, - NEVER - } - Class getAmountType(); - MonetaryContext getDefaultMonetaryContext(); - default MonetaryContext geMaximalMonetaryContext(){...} // default: delegates to getDefaultMonetaryContext() - default QueryInclusionPolicy getQueryInclusionPolicy(){...} // default: QueryInclusionPolicy.ALWAYS - - MonetaryAmountFactory createMonetaryAmountFactory(); - -} -------------------------------------------------------------------------------- - -Hereby - -* +getAmountType()+ returns a new implementation of +T+ which is returned by a +MonetaryAmountFactory+ created by an - instance. -* The default +MonetaryContext+ used can be determined by calling +getDefaultMonetaryContext()+. -* The maximal supported +MonetaryContext+ can be determined by calling +getMaximalMonetaryContext()+. -* +getQueryInclusionPolicy()+ defines if the given spi (and hence the corresponding +MonetaryAmount+ implementation - type) is to be considered, when +Monetary.queryAmountType(MonetaryContext)+ is called: - ** +ALWAYS+ means that given instance should be considered always as a candidate. Nevertheless the active - implementation of +MonetaryAmountSpi+ decides finally, which implementation type (evaluated by calling - +getAmountType()+) is returned as the result of such a query operation, based on the flavors and capabilities - declared by the +MonetaryContext+ provided. - ** +DIRECT_REFERENCE_ONLY+ means that given instance should only be considered as a candidate, when the target type - requested matches the type returned by +getAmountType()+) . - ** +NEVER+ signals that the corresponding implementation type is considered not to be a valid return type of a query - operation. This is useful, e.g. for special amount types as decorators, which do not provide their own numeric - representations. -* +createAmountFactory()+ finally creates a corresponding +MonetaryAmountFactory+ factory. - - -===== Backing the Monetary Singleton (Amount related functionality) -Also the functionality of the +Monetary+ accessor singleton is backed up by two SPI interfaces, called -+javax.money.spi.MonetaryAmountsSingletonSpi+ and +javax.money.spi.MonetaryAmountsSingletonQuerySpi+. Implementations -of these interfaces should rely on the +Bootstrap+ class to access the available instances of +MonetaryAmountFactory+ -and +MonetaryAmountFactoryProviderSpi+ respectively. Nevertheless being able to register alternate implementations -would allow to support more complex rules for a couple of enterprise related functionality such as: - -Implementing +MonetaryAmountsSingletonSpi+ allows -* to provide amount types (and related factories) based on the current runtime context. -* to configure the default amount type, as provided by +Monetary.getDefaultAmountType()+, differently based on - the current runtime context. -* to configure different defaults for the +MonetaryContext+ used by the amount implementation types/factories. - -The interface is defined as follows: - -[source,java] -.Interface MonetaryAmountsSingletonSpi -------------------------------------------------------------------------------- -public interface MonetaryAmountsSingletonSpi{ - MonetaryAmountFactory getAmountFactory(Class amountType); - Class getDefaultAmountType(); - Collection> getAmountTypes(); - - // Modelled as default methods in Java 8 - MonetaryAmountFactory getDefaultAmountFactory(); - Collection> getAmountFactories(); -} -------------------------------------------------------------------------------- - -Hereby - -* +getAmountFactory(Class)+ should return an instance of +MonetaryAmountFactory+ that creates the amount instances. -* +getDefaultAmountType()+ returns the default implementation type created by the factory returned - from +getDefaultAmountFactory()+ for the current runtime context. -* +getAmountTypes()+ should return a collection of available implementation types for the current runtime context. -* +getDefaultAmountFactory()+ should return the default +MonetaryAmountFactory+ for the current context. Hereby an - implementation must never return +null+. If no +MonetaryAmountFactory+ instances are registered, a +MonetaryException+ - should be thrown. -* Similar to +getAmountTypes()+ the method +getAmountFactories()+ returns all corresponding factories for the current - context. - - -Implementing +MonetaryAmountsSingletonQuerySpi+ allows to provide alternate implementations of query algorithm used -within +Monetary.queryAmountType(MonetaryContext)+ to evaluate the best matching +MonetaryAmount+ implementation -given a +MonetaryAmountFactoryQuery+ required. The interface is defined as follows: - -[source,java] -.Interface MonetaryAmountsSingletonQuerySpi -------------------------------------------------------------------------------- -public interface MonetaryAmountsSingletonQuerySpi{ - Collection> getAmountFactories(MonetaryAmountFactoryQuery query); - - // Modelled as default methods in Java 8 - MonetaryAmountFactory getAmountFactory(MonetaryAmountFactoryQuery query); - Class getAmountType(MonetaryAmountFactoryQuery query) - Collection> getAmountTypes(MonetaryAmountFactoryQuery query) - boolean isAvailable(MonetaryAmountFactoryQuery query); -} -------------------------------------------------------------------------------- - -Hereby - -* The only method to be overriden by default is +getAmountFactories(MonetaryAmountFactoryQuery)+, which evaluates - a given +MonetaryAmountFactoryQuery+ and returns the matching +MonetaryAmountFactory+ instances. -* Additionally there are a couple of default methods, which reflect the overall functionality provided from - the +Monetary+ singleton. This gives implementation providers full control about the functionality - executed. Summarizing the methods implemented by default are: - ** +getAmountType(MonetaryAmountFactoryQuery)+ allows to evaluate a +MonetaryAmount+ implementation type that best - covers the requirements defined by the passed +MonetaryAmountFactoryQuery+. If multiple types match the query - and are not resolvable, a +MonetaryException+ should be thrown. - ** +getAmountFactory(MonetaryAmountFactoryQuery)+ matches +getAmountType(MonetaryAmountFactoryQuery)+, but returns - the +MonetaryAmountFactory+ instance instead of the implementation type. - ** +getAmountTypes(MonetaryAmountFactoryQuery)+ allows to evaluate all +MonetaryAmount+ implementation types that - covers the requirements defined by the passed +MonetaryAmountFactoryQuery+. - ** +isAvailable(MonetaryAmountFactoryQuery)+ allows to determine (without any exception thrown) if the given - query returns any types/factories matching. - -In general implementations of this interface should consider the following rules: -. if the +MonetaryAmountFactoryQuery+ passed is explicitly requiring a concrete implementation type, a factory of this - type should be returned given the following conditions are met: - .. the implementation is capable to support the required maximal _scale_. - .. the implementation is capable to support the required maximal _precision_. -. If no concrete type is given (passing the +MonetaryAmount+ interface as type), the following must be checked against - each registered +MonetaryAmountFactoryProviderSpi+ that are eligible as a possible result type footnote:[This is the - case, if the the value from +MonetaryAmountFactoryProviderSpi.getInclusionPolicy()+ does not equal to - +QueryInclusionPolicy.NEVER+, or +QueryInclusionPolicy.DIRECT_REF_ONLY+.] to be returned from a query: - .. is the +MonetaryAmountFactoryProviderSpi+ capable to support the required maximal scale (+required scale <= - maxScale+). - .. is the +MonetaryAmountFactoryProviderSpi+ capable to support the required maximal precision (+required precision - <= maxPrecision, or precision==0/unlimited+). -. Additional attributes to consider may be provided with the +MonetaryAmountFactoryQuery+ provided, though this - specification does not define any further aspects in detail. -. if all of the above is true, the according amount types or amount factories should be returned. - -If one of the conditions above fails a +MonetaryException+ must be thrown footnote:[This makes sense, since acquiring -for a concrete type with invalid capabilities can be seen as a programming error, since the default and maximal -capabilities of a concrete type are accessible from the according implementation factory.], or in case of -+Collection+ being the method's return type, an empty collection should be returned. Also -+isAvailable(MonetaryAmountFactoryQuery)+ should never throw an exception, but return +false+, if no matching -+MonetaryAmountFactoryProviderSpi+ could be determined. - - -[[MonetaryRoundingsSingletonSpi]] -===== Accessing Roundings -Since a monetary rounding is nothing else than a conversion from an unrounded amount to a rounded amount, it is modeled -as +<>+. Nevertheless similar to other artifacts defined by this JSR also roundings have -metadata attached, so roundings extends +<>+ and additionally provide access to the so called -+RoundingContext+. -+MonetaryRounding+ instances are accessed from the +Monetary+ singleton. Similar to other -singletons in this JSR the +Monetarys+ singleton is backed up by an instance of -+MonetaryRoundingsSingletonSpi+, which allows to control the exact logic how registered -+javax.money.spi.RoundingProviderSpi+ are managed: - -[source,java] -.Interface MonetaryRoundingsSingletonSpi -------------------------------------------------------------------------------- -public interface MonetaryRoundingsSingletonSpi { - Collection getRoundings(RoundingQuery query); - MonetaryRounding getDefaultRounding(); - Set getRoundingNames(String... providers); - Set getProviderNames(); - List getDefaultProviderChain(); - - // Modelled as default methods in Java 8 - MonetaryRounding getRounding(RoundingQuery roundingQuery); - MonetaryRounding getRounding(CurrencyUnit currencyUnit, String... providers); - MonetaryRounding getRounding(String roundingName, String... providers); - MonetaryRounding getRounding(RoundingQuery query); - boolean isRoundingAvailable(RoundingQuery query); - boolean isRoundingAvailable(String roundingId, String... providers); - boolean isRoundingAvailable(CurrencyUnit currencyUnit, String... providers); -} -------------------------------------------------------------------------------- - -Similar to <> a provider based service model is defined, meaning -* multiple rounding providers can be registered -* when accessing +MonetaryRounding+ instances the providers and ordering of the provider chain that should handle the - request can be explicitly defined. -* if no chain is passed explicitly a default provider chain is used, configurable within the +javamoney.properties+ - file (see details later). -* +getRoundingNames+ allows to evaluate all explicitly named roundings available from a given set of rounding providers. -* +getProviderNames()+ allows to evaluate the names of the registered providers for the current context. -* +getDefaultProviderChain()+ return the ordered list of provider names representing the default provider chain - used, when no explicit rounding providers are selected. - -Basically all access methods by default delegate to +getRoundings(RoundingQuery)+. Nevertheless all possible -access methods from the +Monetary+ singleton are reflected in the SPI, so implementations have full control of -the logic executed. - -Summarizing: - -* +MonetaryRounding+ instances can be accessed - ** based on a +CurrencyUnit+, hereby returning the default rounding for a given currency. - ** by its explicit (unique) _roundingId_. - ** by passing a +RoundingQuery+ allowing to add arbitrary additional parameters to configure the rounding - returned. - -===== Registering Roundings - -To register additional +MonetaryRounding+ instances of +RoundingProviderSpi+ must be implemented and registered with the current -<> logic: - -[source,java] -.Interface RoundingProviderSpi -------------------------------------------------------------------------------- -public interface RoundingProviderSpi { - MonetaryRounding getRounding(RoundingQuery query); - Set getRoundingNames(); - - // Modelled as default method in Java 8 - String getProviderName(); -} -------------------------------------------------------------------------------- - -Hereby: - -* +getRounding(RoundingQuery)+ should return the matching rounding, given a +RoundingQuery+. If a provider cannot - provide the requested rounding, it should simply return +null+. -* +getRoundingNames()+ returns all rounding names of the explicitly accessible roundings provided by this rounding - provider. It is within the responsibility of the implementation of +MonetaryRoundingsSingletonSpi+ to collect all - rounding names contributed by providers to built the full list of rounding names. -* Similar to other providers in this JSR each rounding provider must declare an explicit unique name provided by the - +getProviderName()+ method. - -Implementations of this JSR should also consider additional aspects: - -. When providing roundings targeting currencies, _by default_, if no explicit rounding is available for a given - +CurrencyUnit+, the digits returned from +CurrencyUnit.getDefaultFractionDigits()+ and +RoundingMode.HALF_EVEN+ - should be used, to create a rounding for a given +CurrencyUnit+. -. Under Java SE (or where available) reference implementations should also provide _default_ arithmetic rounding - instances, e.g. you can set a maximal scale of +1+ and a +RoundingMode+ as an additional attribute. -. Implementations should also support cash rounding. E.g. in Switzerland default rounding is done for a scale of +2+, - whereas when paying in cash, the minor units must be divisible by +5+, since +5+ is the smallest coin possible. -. Finally it may also possible to provide _historic_ roundings hereby considering an additional target date/time, e.g. - modeled as +LocalDate+. - - -[[CurrencyConversionSpi]] -==== Currency Conversion SPI - -===== Accessing Currency Conversion Artifacts - -Currency Conversion and rate providers mechanisms are provided by the +MonetaryConversions+ singleton -(see <>). This singleton is backed up by an implementation of -+javax.money.spi.MonetaryConversionsSingletonSpi+. Implementing this SPI provides full control about the singleton’s -effective behaviour. As a consequence the methods to be implemented basically match the ones defined by the -+MonetaryConversions+ class: - -[source,java] -.Interface MonetaryConversionsSingletonSpi -------------------------------------------------------------------------------- -public interface MonetaryConversionsSingletonSpi { - ExchangeRateProvider getExchangeRateProvider(ConversionQuery conversionQuery); - Collection getProviderNames(); - List getDefaultProviderChain(); - - // Modelled as default methods in Java 8 - ExchangeRateProvider getExchangeRateProvider(String... providers); - List getExchangeRateProviders(String... providers); - boolean isExchangeRateProviderAvailable(ConversionQuery conversionQuery); - CurrencyConversion getConversion(ConversionQuery conversionQuery); - CurrencyConversion getConversion(CurrencyUnit termCurrency, String... providers); - boolean isConversionAvailable(ConversionQuery conversionQuery); - boolean isConversionAvailable(CurrencyUnit termCurrency, String... providers); -} -------------------------------------------------------------------------------- - -Hereby - -* multiple +ExchangeRateProvider+ instances can be registered. -* each +ExchangeRateProvider+ is identified by it's (unique) name, accessible from - +ExchangeRateProvider.getContext().getProviderName()+. -* +getProviderNames()+ allows to evaluate the names of the registered providers for the current context. -* +getDefaultProviderChain()+ return the ordered list of provider names representing the default provider chain - used, when no explicit rounding providers are selected. -* +ExchangeRateProvider+ instances can be accessed directly by passing the single provider name only as the target - chain definition, e.g. the provider 'XY' can be accessed by calling +getExchangeRateProvider("XY")+. -* the main artifact defining currency conversion is an +ExchangeRateProvider+. It provides +ExchangeRate+ instances - defining the factor for converting an base amount to a target (aka _terminating_) amount. -* A +CurrencyConversion+ basically is only an adapter to an +ExchangeRateProvider+, which allows simple use of - conversion as a +MonetaryOperator+. -* +getExchangeRateProvider(String…)+ allows to pass an ordered array of provider names. The names identify the - providers to be used allow to define a _composite_ +ExchangeRateProvider+ instance (modeling a provider chain), - that is able to answer requests based on multiple rate providers. As an example calling +ExchangeRateProvider prov = - getExchangeRateProvider(“ECB”, “IMF”)+ should by default return a _composite_ +ExchangeRateProvider+ instance, that - internally first tries to resolve an +ExchangeRate+ requested, using the provider named "ECB". On success the "ECB" - rate should be returned. If this fails, to whatever reason, the provider with name "IMF" should be tried. If no - provider is able to return a valid result, a +CurrencyConversionException+ must be thrown as defined in the - corresponding +ExchangeRateProvider+ interface API documentation. -* If no explicit provider names are passed, the provider names and ordering as defined by - +getDefaultProviderChain()+ have to be used. -* Implementations can easily provide alternate combination policies, but defining a corresponding configuration flag - that can be passed to a +ConversionQuery+ and that must be interpreted by the registered - +MonetaryConversionsSingletonSpi+ implementation, e.g. - -[source, java] -------------------------------------------------------------------------------- -ExchangeRateProvider rateProvider = getExchangeRateProvider(ConversionQueryBuilder.of() - .setProviders("XY", "foo") - .set(MyProviderCombiationPolicy.CHEAPEST_CONTRACT_FIRST) - .build()); -------------------------------------------------------------------------------- - -Basically all access methods by default delegate to +getExchangeRateProvider(ConversionQuery)+. Nevertheless all possible -access methods from the +MonetaryConversions+ singleton are reflected in the SPI, so implementations have full control of -the logic executed. - - -===== Adding Currency Conversion Capabilities -Adding additional capabilities for currency conversion equals to implementing and registering classes implementing the -+ExchangeRateProvider+ interface. The interface itself is part of the API and described in +<>+ -and +<>+. - -Implementations of the +MonetaryConversionsSingletonSpi+ should use the current <> implementation -to load right providers to be used for a given runtime context. - - -[[FormattingSPI]] -==== Formatting SPI -[[MonetaryFormatsSingletonSpi]] -===== Accessing Monetary Amount Formats - -Amount Formats are provided by the +MonetaryFormats+ singleton (see <>). This singleton is -backed up by an implementation of +javax.money.spi.MonetaryFormatsSingletonSpi+. Implementing this SPI provides -full control about the singleton’s effective behaviour. As a consequence the methods to be implemented basically -match the ones defined by the +MonetaryFormats+ class: - -[source,java] -.Interface MonetaryFormatsSingletonSpi -------------------------------------------------------------------------------- -public interface MonetaryFormatsSingletonSpi { - Collection getAmountFormats(AmountFormatQuery formatQuery); - Set getAvailableLocales(String... providers); - Set getProviderNames(); - List getDefaultProviderChain(); - - // Modelled as default methods in Java 8 - MonetaryAmountFormat getAmountFormat(Locale locale, String... providers); - MonetaryAmountFormat getAmountFormat(String formatName, String... providers); - MonetaryAmountFormat getAmountFormat(AmountFormatQuery formatQuery); - boolean isAvailable(AmountFormatQuery formatQuery); - boolean isAvailable(Locale locale, String... providers); -} -------------------------------------------------------------------------------- - -Hereby - -* multiple +MonetaryAmountFormat+ instances can be accessed, provided by registered instances of - +MonetaryAmountFormatProviderSpi+ (see next section for details), whereby each provider spi is identified - by a unique provider name. -* +getProviderNames()+ allows to evaluate the names of the registered providers for the current context. -* +getDefaultProviderChain()+ return the ordered list of provider names representing the default provider chain - used, when no explicit rounding providers are selected. -* Instances of +MonetaryAmountFormat+ can be identified and accessed using a format name. -* Instances of +MonetaryAmountFormat+ can be accessed using a target +Locale+. -* When accessing +MonetaryAmountFormat+ instances, the provider chain to be used can be defined explicitly by passing - the ordered provider names. If no explicit provider names are passed, the provider names and ordering as defined by - +getDefaultProviderChain()+ have to be used. -* +getAvailableLocales()+ allows to access the locales for which providers can return formats. - -Basically all access methods by default delegate to +getAmountFormat(AmountFormatQuery)+. Nevertheless all possible -access methods from the +MonetaryFormats+ singleton are reflected in the SPI, so implementations have full control of -the logic executed. - -[[MonetaryAmountFormatProviderSpi]] -===== Adding Amount Formats -The +MonetaryFormats+ singleton delegates access to +MonetaryAmountFormat+ instances to the registered -+MonetaryFormatsSingletonSpi+ instance. The ladder class is responsible to manage the registered instances of -+javax.money.spi.MonetaryAmountFormatProviderSpi+ to evaluate the correct results: - -[source,java] -.Interface MonetaryAmountFormatProviderSpi -------------------------------------------------------------------------------- -public interface MonetaryAmountFormatProviderSpi { - Collection getAmountFormats(AmountFormatQuery formatQuery); - Set getAvailableLocales(); - Set getAvailableFormatNames(); - - // Modelled as default method in Java 8 - String getProviderName(); -} -------------------------------------------------------------------------------- - -Hereby -* +getProviderName()+ defines the (unique) provider name that can be used to reference this format provider either - explicitly when accessing format instances or when configuring the default provider chain. -* at least one instance of +MonetaryAmountFormatProviderSpi+ must be registered to the <> logic. -* +getAmountFormats(AmountFormatQuery)+ returns the corresponding +MonetaryAmountFormat+ instances that match the given - query. If the query doe not match, an empty collection should be returned. -* +getAvailableLocales()+ returns the locales for which instances of +MonetaryAmountFormat+ can be accessed. -* +getAvailableFormatNames()+ returns the explicit format names for whcih instances of +MonetaryAmountFormat+ can be - accessed explicitly from a provider. - - -[[Bootstrap]] -==== The Bootstrapping Mechanism -===== Overview -Basically the +Bootstrap+ singleton class is used by all API components to access instances of the different pluggable -components of the Money API. Hereby also the +Bootstrap+ class delegates the location and loading of services to an -implementation of a +javax.money.spi.ServiceProvider+, which implements the detailed logic how services are located and -managed. If no +ServiceProvider+ is configured, a default implementation is used that uses the -+java.util.ServiceLoader+ to load and locate the instances. - -Hereby the methods on the +ServiceProvider+, reflect the main functionality of the overall +Bootstrap+ class: - -[source,java] -.Class Bootstrap -------------------------------------------------------------------------------- -public final class Bootstrap{ - public static ServiceProvider init(ServiceProvider serviceProvider); - public static Collection getServices(Class serviceType){...} - public static T getService(Class serviceType) {...} -} -------------------------------------------------------------------------------- - -Summarizing the +Bootstrap+ singleton - -* Tries to load an instance of +ServiceProvider+ using +java.util.ServiceLoader+. -* if no implementation was registered, it falls back to a default provider implementation, delegating to - +java.util.ServiceLoader+ and with no specific ordering/priorization mechanism. -* if _exact one_ implementation is registered, this implementation is used for loading/accessing the services required - by the JSR 354 API. The implementation of +ServiceLoader+ hereby can also implement a contextual service registry. -* if _multiple_ implementations are registered, the implementation is not defined, Hereby a warning is logged. - -===== Service Provider -To use an alternate implementation of +javax.money.spi.ServiceProvider+ it must be registered -using the +java.util.ServiceLoader+. If no instance is registered, an instance of +DefaultServiceProvider+ is loaded, -that relies on the +java.util.ServiceLoader+. - -Implementations of +javax.money.spi.ServiceProvider+ must implement methods similar as available on the +Bootstrap+ -singleton class: - -[source,java] -.Interface ServiceProvider -------------------------------------------------------------------------------- -@FunctionalInterface -public interface ServiceProvider { - Collection getServices(Class serviceType){...} -} -------------------------------------------------------------------------------- - -Hereby - -* if a required service type can not be satisfied, an empty Collection should be returned. - - -===== Support for EE / CDI -We have seen that all the singleton accessors defined by this API can be replaced by customized implementations. This -allows also to adapt the behaviour in case your application runs in a EE/CDI context. Given this all singleton -backing implementations should delegate to the bootstrap component's +ServiceProvider+ to evaluate the right -instances of components given a special type. As a consequence integration with Java EE can be done in multiple ways: - -* you can override the singleton SPIs (+MonetaryAmountsSingletonSpi, MonetarFormatsSingletonSpi, MonetaryRoundingsSpi, -MonetaryConversionsSingletonSpi, MonetaryFormatsSingletonSpi+ and reimplement the mechanism how the different -components are located within the current runtime environment. Additionally you can filter or adapt the components -accessible, e.g. based on tenant or other contextual information. Overriding the singletons gives you full control. -Nevertheless overriding the SPIs requires more knowledge about the specification. Basically we recommended to -execute the TCK to identify locations, where your implementation may not be compliant with this spec, when using -this approach. -* Far more easy is to reuse the default singleton implementations, but exchange the +ServiceProvider+ used. This is - basically quite easy: - ** Implement an alternative instance of +ServiceProvider+. - ** Register the instance using the JDK's +ServiceLoader+: add a file with the following content to your (system) - classpath under +/META-INF/services/javax.money.spi.ServiceProvider+: - -[listing] -.Register alternate ServiceLoader in +/META-INF/services/javax.money.spi.ServiceProvider+ -------------------------------------------------------------------------------- -foo.bar.MyFooServiceProvider -------------------------------------------------------------------------------- - -This will delegate all requests for SPIs to your +foo.bar.MyFooServiceProvider+ implementation. Within this -implementation you must: -* fall back on SE mechanism, when EE/CDI is not available. -* locate the components as required -* enable component precedence by ordering the instances found, e.g. you can base your ordering on +@Priority+ - annotations on the classes loaded. Hereby the components with higher priority must be returned first. They - either have precedence in command chains or are selected as final components to be used, e.g. for backing singleton - beans. - -An according example is implemented within the <> library, basically it looks similar to the following code: - -[source,java] -.Outline of a CDI based ServiceLoader -------------------------------------------------------------------------------- -@ServicePriority(ServicePriority.NORM_PRIORITY + 1) -public class CDIServices implements ServiceProvider { - - @Override - public List getServices(Class serviceType) { - List instances = new ArrayList(); - for(T t: ServiceLoader.load(serviceType)){ - instances.add(t); - } - for (T t : CDIContainer // backed up by CDI.current().getBeanManager(); - .getInstances(serviceType)) { - instances.add(t); - } - Collections.sort(instances, PrioritySorter::sort); - return instances; - } - -} - -------------------------------------------------------------------------------- - -As a side effect you may add additional functionality to your setup: - -* For example you may write a CDI portable extension to add the service that are registered using the JDK - +ServiceLoader+ to your CDI runtime context. -* With CDI you can, of course, register your SPI implementations simply by implementing them as CDI managed - beans: - * You still can use the +ServiceLoader+ to register your beans. - -[source,java] -.Example writing a CurrencyProvider with CDI -------------------------------------------------------------------------------- -@Priority(100) -@Singleton -public class MyCurrencyProvider implements CurrencyProvider { - - private final Map currencies = new HashMap<>(); - - public MyCurrencyProvider(){ - this.currencies.put("MSCU", new MyCurrency()); - } - - [...] -} -------------------------------------------------------------------------------- - -[[LoggingSpi]] -==== Adapting the Logging Backend -By default the JSR API logic uses +java.util.logging+ (JUL) as logging backend. JUL allows to configure additional or -customized logging Handler instances, so alternate logging backends can be used easily, by registering a forwarding -+Handler+ implementation for +javax.money+ and configuring the +Logger+ instance to not delegating to its parent loggers. - -The implementation that implements the API’s SPI may use a different logging approach. - - -[[MetadataModeling]] -== Meta-Data Contexts and Query Models == -=== Overview === - -The JSR uses a unified meta-data model to support more advanced use cases, which are not explicitly specified. -The main reason for not specifying these aspects is that they are highly use case and organization dependent. -In general there are two flavors of meta-data used throughout the JSR: - -. _Contexts_ provide additional information on value types or services, such as currencies, amounts, conversions or - formats. Contexts are accessible directly from the corresponding value types, by calling methods named - +getContext()+. -. _Queries_ models a generic and flexible way to configure/parametrize services for accessing currencies, amounts, - conversions or formats. Queries can be passed to the different accessor singletons, and also are forwarded to the SPI - implementations effectively providing the data/services required. - -Similarly there are two abstract base classes provided: - -. +AbstractContext+ models an abstract base type, which is extended by all context implementations within this JSR, - such as +MonetaryContext, CurrencyContext, RoundingContext, ProviderContext, ConversionContext, AmountFormatContext+. -. +AbstractQuery+ models an abstract base query, which is extended by all query implementations within this JSR, - such as +MonetaryAmountFactoryQuery, CurrencyQuery, RoundingQuery, ConversionQuery, AmountFormatQuery+. - -The following sections give further information on these concepts. - - - -[[AbstractContext]] -=== AbstractContext === - -The abstract class +AbstractContext+ models a base type, which is extended by all context implementations within this -JSR, such as +MonetaryContext, CurrencyContext, RoundingContext, ProviderContext, ConversionContext, -AmountFormatContext+. Basically this class models a generic data container, which provides a type safe mechanism for -retrieving meta-data: - -[source,java] -.Class AbstractContext -------------------------------------------------------------------------------- -public abstract class AbstractContext -implements Serializable{ - ... - public String getProviderName(); - - public Boolean getBoolean(String key); - public Integer getInt(String key); - public Long getLong(String key); - public Float getFloat(String key); - public Double getDouble(String key); - public String getText(String key); - public T get(Class type); - public T get(String key, Class type); - - public boolean isEmpty(); - public Class getType(String key); - public Set getKeys(Class type) -} -------------------------------------------------------------------------------- - -Hereby - -* each context instance is related to a provider, that created the context, accessible from +getProviderName()+. -* additional attributes can be set, which models a type safe interface for adding properties, without - duplicating artifacts or creating non portable dependencies. - ** identified by the attribute’s type. - ** identified an arbitrary literal key -* the +getXXX, get+ methods only return values of the resulting type is assignment compatible, so no class cast - exceptions do occur. - -The classes extending this class hereby are thread-safe and immutable: - -* +javax.money.CurrencyContext+ -* +javax.money.MonetaryContext+ -* +javax.money.RoundingContext+ -* +javax.money.convert.ProviderContext+ -* +javax.money.convert.ConversionContext+ -* +javax.money.format.AmountFormatContext+ - -Creation of context instances is encapsulated using corresponding builder instances: - -* +javax.money.CurrencyContextBuilder+ -* +javax.money.MonetaryContextBuilder+ -* +javax.money.RoundingContextBuilder+ -* +javax.money.convert.ProviderContextBuilder+ -* +javax.money.convert.ConversionContextBuilder+ -* +javax.money.format.AmountFormatContextBuilder+ - -The builders hereby extend +AbstractContestBuilder+, discussed in the following section. - -[[AbstractContextBuilder]] -=== Abstract Class AbstractContextBuilder === - -The abstract class +AbstractContextBuilder+ models a base builder type, which is extended by all context builder -implementations within this JSR, such as +MonetaryContextBuilder, CurrencyContextBuilder, RoundingContextBuilder, -ProviderContextBuilder, ConversionContextBuilder, AmountFormatContextBuilder+. Basically this class models a generic -builder, which provides a type safe mechanism for storing arbitrary meta-data: - -[source,java] -.Class AbstractContextBuilder -------------------------------------------------------------------------------- -public abstract class AbstractContextBuilder -implements Serializable{ - public B setProviderName(String provider); - - public B set(Object value); - public B set(T value, Class type); - public B set(String key, Object value); - public B set(String key, T value, Class type) - public B set(String key, int value); - public B set(String key, long value); - public B set(String key, float value); - public B set(String key, double value); - - public B importContext(AbstractContext context, boolean overwriteDuplicates); - public B importContext(AbstractContext context); - public B removeAttributes(String... keys); - - public abstract C build(); - -} -------------------------------------------------------------------------------- - -[[AbstractQuery]] -=== Abstract Class AbstractQuery === - -The abstract class +AbstractQuery+ models a base query type, which is extended by all query -implementations within this JSR, such as +MonetaryAmountFactoryQuery, CurrencyQuery, RoundingQuery, -ConversionQuery, AmountFormatQuery+. Basically this class models a generic -query, which provides a type safe mechanism for storing arbitrary query-data: - -[source,java] -.Abstract class AbstractQuery -------------------------------------------------------------------------------- -public abstract class AbstractQuery extends AbstractContext{ - - protected AbstractQuery(AbstractQueryBuilder builder); - - public List getProviderNames(); - public Class getTargetType(); - -} -------------------------------------------------------------------------------- - -As seen above a query is basically the same as a context, thus inheriting all attribute container functions. -The query provides basic query properties: - -* a query contains the provider names that defines the provider chain to be used for answering the query. If not set - the corresponding default provider chain must be used. The providers available are accessible by calling - +getProviderNames()+ on the corresponding singleton accessors/SPI interfaces, e.g. - +Monetary.getCurrencyProviderNames+, +Monetary.getRoundingProviderNames+, +MonetaryConversions.getProviderNames+ - etc. -* a query may defines a target type, hereby defining the target result type expected. - -Hereby +AbstractQuery+ inherits most of the functionality from the +<>+ -super class. - - -[[AbstractQueryBuilder]] -=== Abstract Class AbstractQueryBuilder === - -The abstract class +AbstractQueryBuilder+ models a base builder type, which is extended by all query builder -implementations within this JSR, such as +MonetaryAmountFactoryQueryBuilder, CurrencyQueryBuilder, RoundingQueryBuilder, -ConversionQueryBuilder, AmountFormatQueryBuilder+. Basically this class models a generic builder, which provides a -type safe mechanism for storing arbitrary query-data: - -[source,java] -.Abstract class AbstractQueryBuilder -------------------------------------------------------------------------------- -public abstract class AbstractQueryBuilder - extends AbstractContextBuilder{ - ... - public B setProviderNames(String... providers); - public B setProviderNames(List providers); - public B setTargetType(Class type); -} -------------------------------------------------------------------------------- - -Similarly to +AbstractQuery+ also here most of the functionality is inherited by the +<>+ -super class. - - -[[Recommendations]] -== Implementation Recommendations -=== Overview -There are a couple of best practices in the area of financial applications and frameworks. This JSR does not require -most of them for the following reasons: - -* The overall API design is similar to the Date/Time API introduced with JDK 8 (JSR-310), where appropriate. - E.g. +TemporalAdjuster+ and +MonetaryOperator+ model a similar concept for temporal and for monetary amounts. - Therefore the corresponding models in this JSR define similar implementation constraints. -* More complex constraints would be difficult or impossible to ensure by a TCK, so they are defined as recommendations. -* Finally there is always the possibility that no common ground can be found for the way some functionality can be - modeled generically across implementations. It would then be the responsibility of the implementers to follow best, - or at least _de-facto_, practice. - -Nevertheless we think some practices are important and should be followed by implementations, so we added the most -relevant ones in the following sections. - - -=== Monetary Arithmetic -When dealing with monetary amounts the following aspects should be considered: - -* Arithmetic operations should throw an +ArithmeticException+, if performing arithmetic operations between amounts - exceeds the capabilities of the numeric representation type used. Any implicit truncating, that would lead to complete - invalid and useless results, should be avoided, since it may result to invalid results, which are very difficult to - trace. This recommendation does not affect internal rounding, as required by the internal numeric representation of a - +MonetaryAmount+. -* When adding or subtracting amounts, best practice recommends to use parameters that are instances of +MonetaryAmount+, - hereby ensuring that both amounts have the same currency. -* When multiplying or dividing amount, best practice recommends parameters that are simple numeric values. -* Arguments of type +java.lang.Number+ should be used with caution, since extracting its numeric value in a feasible way - is not trivial. -* Arithmetic operations should honor the advanced rules how rounding and truncation should be handled. Refer to the - following sections for further details. - -[[NumericPrecision]] -=== Numeric Precision -For financial applications precision and rounding is a very important aspect. Additionally that an incorrect arithmetic -obviously has direct financial consequences, also legal aspects require specific precision and rounding to by applied. -The JSR's expert group identified the following important and distinct precision types: - -* Internal precision -* External precision -* Formatting precision - -The following sections will explain things in more detail. - -[[InternalPrecision]] -==== Internal Precision -Overview:: -This precision type is the most important one, since it is directly related/determined by the internal numeric -representation of the class implementing +MonetaryAmount+. Hereby: - -* The internal numeric capabilities of a +MonetaryAmount+ typically exceed the scale implied by the corresponding - currency. Internal rounding must be done after each operation, but this rounding has nothing in common with the - rounding implied by the currency attached. Basically the monetary arithmetics are completely independent of the - currency, or in other words rounding should only be done implicitly when required by the internal numeric - representation to minimize the loss of numeric precision. -* For calculations that require high scaled results, e.g. financial product calculations, it is recommended to work - with relatively high scales, e.g. +64+ or even higher scales, as provided by the +BigDecimal+ class footnote:[Therefore - the default reference implementation class, +Money+,is based on +BigDecimal+ and allows to explicitly configure - its +MathContext+ used on creation.]. On the - other hand when monetary arithmetics must be fast, e.g. in trading, scale requirements are often reduced in favor - of fast data manipulation. This contradictory requirements were basically the key reason, why the model for - +MonetaryAmount+ does not explicitly specify the numeric representation to be used. -* Additionally during a financial calculation, the points, where rounding is feasible, are basically use case dependent - and therefore should not be performed by a +MonetaryAmount+ implementation implicitly. Instead of, roundings can be - applied as useful as monetary adjustments explicitly, when useful. -* Also worth to mention is that for the same currency different roundings may be defined (default rounding, cash rounding, - special rounding for presentation purposes), so there is no such concept as _THE_ rounding for a monetary amount. - -Configuring and Changing Internal Precision:: -An implementation of +MonetaryAmount+ may support changing the internal precision or numeric capabilities. But any -value type semantics must be strictly obeyed, meaning that changing a monetary amount’s internal precision or numeric -capabilities, requires creating of a new instance. - -Additionally if an implementation of a +MonetaryAmount+ supports different numeric capabilities, it is useful to allow -the default capabilities to be configurable. Hereby a mechanism should be used, that is not shared in EE runtime context, -such as a property file in the classpath. - -Inheriting Numeric Representation Capabilities:: -When performing calculations with the value type semantics new instances of amounts are created for each calculation -performed. This implies additional constraints: - -* By inheriting the +MonetaryAmount+ implementation type to its return types of all arithmetic operations, also the - numeric capabilities must be inherited. -* Finally a +MonetaryAmount+ implementation is required to throw an +ArithmeticException+, if a client tries to create - a new instance with a numeric value that exceeds its internal representation capabilities. Since each arithmetic - operation requires the creation of a new amount instance, as a consequence, all operations that exceed the numeric - capabilities must throw an +ArithmeticException+ (basically no implicit truncation is allowed). - -[[ExternalPrecision]] -==== External Precision -External precision is the precision applied, when the numeric part of a +MonetaryAmount+ is externalized, meaning a -numeric part of an amount is accessed/converted into another numeric representation (e.g. calling +getNumber(Class), -getNumberExact(Class)+). This externalized representation may have reduced numeric capabilities compared to the internal -numeric representation, so truncation must be performed, or some exception can be thrown. Generally a precision or scale -reduction on externalization should never throw an exception, despite the method variants are defined to be exact, -similar to +BigDecimal.longValueExact()+. The exact methods should then throw an exception, if the externalization -would result in data loss (some sort of truncation must be performed). - -[[DisplayPrecision]] -==== Display Precision -The precision used for displaying of monetary amounts on the screen, a printout or for passing values through technical -systems, is completely dependent on the use cases. This JSR supports these scenarios with the possibility to apply -arbitrary monetary adjustments (modeled as +MonetaryOperator+). - - -== Examples -The following sections illustrate the API’s usage in more detail. - -=== Working with org.javamoney.moneta.Money -A reference implementation of this JSR has to provide value type classes for monetary amounts, hereby implementing -+MonetaryAmount+, and registering at least one implementation class with the +Monetary+ singleton by -implementing and registering a corresponding +MonetayAmountFactory+ instance. - -As an example the reference implementation provides a class +org.javamoney.moneta.Money+, which is using -+java.math.BigDecimal+ internally: - -[source,java] -.Class Money -------------------------------------------------------------------------------- -public final class Money -implements MonetaryAmount, Comparable, Serializable, CurrencySupplier { - ... -} -------------------------------------------------------------------------------- - -The +MonetaryContext+ (by default) hereby is defined as follows: - -[listing] -.Default MonetaryContext settings -------------------------------------------------------------------------------- -maxPrecision = 64; // may be extended arbitrarily -maxScale = -1; // unbounded -numeric class = java.math.BigDecimal -attributes: RoundingMode.HALF_EVEN. -------------------------------------------------------------------------------- - -Since a corresponding +MonetaryAmountFactory+ is registered, a new instance can be created using the typed factory: - -[source,java] -.Example Usage of MonetaryAmountFactory -------------------------------------------------------------------- -MonetaryAmountFactory fact = Monetary.getAmountFactory(Money.class); -Money m = fact.withCurrency("USD").with(200.50).create(); -------------------------------------------------------------------- - -Also a generic +MonetaryAmount+ instance can be accessed using a raw factory (hereby it depends on the configured -default amount factory, which effective type instance is returned): - -[source,java] -.Example Usage MonetaryAmountFactory -------------------------------------------------------------------- -MonetaryAmount amt = Monetary.getDefaultAmountFactory() - .withCurrency("USD").with(200.50).create(); -------------------------------------------------------------------- - -Still we can evaluate the effective amount’s type effectively: - -[source,java] -------------------------------------------------------------------------------- -if(Money.class==amt.getClass()){ - Money m = (Money)amt; -} -------------------------------------------------------------------------------- - -But in general, we do not need to know the exact implementation in most cases, since we can access amount -meta-data as a +MonetaryContext+, This meta-data provides information, such as the maximal precision, maximal scale -supported by the type's implementation as well as other attributes. Refer to <> for more details. - -[source,java] -.Example Usage MonetaryContext -------------------------------------------------------------------- -MonetaryContext ctx = m.getMonetaryContext(); -if(ctx.getMaxPrecision()==0){ - System.out.println("Unbounded maximal precision."); -} -if(ctx.getMaxScale()>=5){ - System.out.println("Sufficient scale for our use case, go for it."); -} -------------------------------------------------------------------- - -Finally performing arithmetic operations in both above scenarios works similar as it is when using -+java.math.BigDecimal+: - -[source,java] -.Example Usage Monetary Arithmetic -------------------------------------------------------------------- -MonetaryAmount amt = ...; -amt = amt.multiply(2.0).subtract(1.345); -------------------------------------------------------------------- - -Also the sample above illustrates how algorithmic operations can be chained together using a fluent API. As -mentioned also external functionality can be chained, e.g. using instances of +MonetaryOperator+: - -[source,java] -.Example Function Chaining footnote:[+MonetaryFunctions+ is not part of the JSR, its just for illustration purposes.] -------------------------------------------------------------------- -MonetaryAmount amt = ...; -amt = amt.multiply(2.12345).with(Monetary.getDefaultRounding()) - .with(MonetaryFunctions.minimal(100)). - .multiply(2.12345).with(Monetary.getDefaultRounding()) - .with(MonetaryFunctions.percent(23)); -------------------------------------------------------------------- - -==== Numeric Precision and Scale -Since the +Money+ implementation class, which is part of the reference implementation, internally uses -+java.math.BigDecimal+ the numeric capabilities match exact the capabilities of +BigDecimal+. -When accessing +MonetaryAmountFactory+ instances it is possible to configure the +MathContext+ effectively used -(by default +Money+ uses +MathContext.DECIMAL64+).: - -[source,java] -.Example Configuring a +MonetaryAmountFactory+, using the RI class +Money+ as example. -------------------------------------------------------------------- -MonetaryAmountFactory fact = Monetary.getAmountFactory( - MonetaryAmountFactoryQueryBuilder.of(Money.class) - .set(new MathContext(250, RoundingMode.HALF_DOWN)).build() -); -// Creates an instance of Money with the given MathContext -MonetaryAmount m1 = fact.setCurrency("CHF").setNumber(250.34).create(); -Money m2 = fact.setCurrency("CHF").setNumber(250.34).create(); -------------------------------------------------------------------- - -==== Extending the API -Now, one last thing to discuss is, how users can add their own functionality, e.g. by writing their own -+MonetaryOperator+ functions. Basically there are two distinct usage scenarios: - -* When the basic arithmetic defined on each +MonetaryAmount+ are sufficient, it should be easy to implement such - functionality, since its behaving like any other type, e.g. - -[source,java] -------------------------------------------------------------------------------- -public final class DuplicateOp implements MonetaryOperator{ - public T apply(T amount){ - return (T) amount.multiply(2); - } -} -------------------------------------------------------------------------------- - -Hereby the amount type implicitly will throw an +ArithemticException+ if the numeric capabilities are not capable of -creating the result required. - -* In case where the basic operations are not sufficient anymore, or it is more convenient to do a calculation - externally, it is still not necessary to cast to any implementation type, since - ** the numeric capabilities can be evaluated using the +MonetaryContext+. On +<>+ both the - default and the maximal supported +MonetaryContext+ can be accessed. - ** the numeric value can be extracted in a portable way accessing the +NumberValue+. - ** a +MonetaryFactory+ can be created to create the result of the same implementation type, without having to cast to - this type ever explicitly. - -Below is a rather academical example of a +MonetaryOperator+ that simply converts any given amount to an amount with -the same numeric value, but with XXX (undefined) as currency: - -[source,java] -.Simple example of a +MonetaryOperstor+ using the +MonetaryAmountFactory+ provided. -------------------------------------------------------------------------------- -public final class ToInvalid implements MonetaryOperator{ - public T apply(T amount){ - return (T)amount.getFactory().setCurrency("XXX").create(); - } -} -------------------------------------------------------------------------------- - -=== Working with org.javamoney.moneta.FastMoney -This class implements a +MonetaryAmount+ using long as numeric representation, whereas the full amount is interpreted -as minor units, with a _denumerator_ of +100000+. - -As an example +CHF 2.5+ is internally stored as +CHF 250000+. Addition and subtraction of values is trivial, whereas -division and multiplication get complex with non integral values. Compared to +Money+ the possible amounts to be modeled -are limited to an overall precision of +18+ and a _fixed scale_ of +5+ digits. - -Beside that the overall handling of +FastMoney+ is similar to +Money+. So we could rewrite the former example by -just replacing +FastMoney+ with +Money+: - -[source,java] -.Usage Example - FastMoney -------------------------------------------------------------------- -MonetaryAmountFactory fact = Monetary.getAmountFactory(FastMoney.class); -// Creates an instance of Money with the given MathContext -MonetaryAmount m1 = fact.setCurrency("CHF").setNumber(250.34).create(); -FastMoney m2 = fact.setCurrency("CHF").setNumber(250.34).create(); -------------------------------------------------------------------- - -Of course, the +MonetaryContext+ is different than for +Money+: - -.The MonetaryContext of FastMoney -------------------------------------------------------------------------------- -maxPrecision = 18; // hard limit -maxScale = 5; // fixed scale -numeric class = Long -attributes: RoundingMode.HALF_EVEN -------------------------------------------------------------------------------- - -=== Calculating a Total -A total of amounts can be calculated in multiple ways, one way is simply to chain the amounts with +add(MonetaryAmount)+: - -[source,java] -.Usage Example Calculating a Total -------------------------------------------------------------------- -MonetaryAmount[] params = new MonetaryAmount[]{ - Money.of("CHF", 100), Money.of("CHF", 10.20), - Money.of("CHF", 1.15),}; -MonetaryAmount total = params[0]; -for(int i=1; i> T apply(T amount){ - if(total==null){ - total = amount; - } - else{ - total = total.add(amount); - } - // ensure to return correct type, since different implementations - // can be passed as amount parameter - return amount.getFactory().with(total).create(); - } - - - public MonetaryAmount getTotal(){ - return total; - } - - public T getTotal(Class amountType){ - return Monetary.getAmountFactory(amountType).with(total).create(); - } - -} -------------------------------------------------------------------- - -[IMPORTANT] -======================================================================= -We are well aware of the fact that this implementation still has some severe drawbacks, but we decided for -simplicity to not add the following features to this example: - -* the implementation can only handle one currency, a better implementation could also be _multi-currency_ capable. -* The implementation above is not thread-safe. -======================================================================= - -Now with the +MonetaryOperator+ totalizing looks as follows: - -[source,java] -.Example Using Total/add method -------------------------------------------------------------------- -Total total = new Total(); -for(int i=1; i T presentValue( - T amt, BigDecimal rate, int periods){ - BigDecimal divisor = BigDecimal.ONE.add(rate).pow(periods); - // cast should be safe for implementations that adhere to this spec - return (T)amt.divide(divisor); -} -------------------------------------------------------------------- - -This algorithm can be implemented as +MonetaryOperator+: - -[source,java] -.Example Implementing a MonetaryOperator -------------------------------------------------------------------- -public final class PresentValue implements MonetaryOperator{ - private BigDecimal rate; - private int periods; - private BigDecimal divisor; - - public PresentValue(BigDecimal rate, int periods){ - Objects.requireNotNull(rate); - this.rate = rate; - this.periods = periods; - this.divisor = BigDecimal.ONE.add(periods).power(periods); - } - - public int getPeriods(){ return periods; } - - public BigDecimal getRate(){ return rate; } - - public T apply(T amount){ - // cast should be safe for implementations that adhere to this spec - return (T)amount.divide(divisor); - } - - public String toString(){...} -} -------------------------------------------------------------------- - -For simplicity we did not add additional feature such as caching of PresentValue instances using a static factory -method, or pre-calculation of divisor matrices. Now given the +MonetaryOperator+ a present value can be -calculated as follows: - -[source,java] -.Example Using a Financial Function -------------------------------------------------------------------- -Money m = Money.of("CHF", 1000); -// present value for an amount of 100, available in two periods, -// with a rate of 5%. -Money pv = m.with(new PresentValue(new BigDecimal("0.05"), 2)); -------------------------------------------------------------------- - - -=== Performing Currency Conversion -Currency Conversion also is a special case of a +MonetaryOperator+ since it creates a new amount based on another -amount. Hereby by the conversion the resulting amount will typically have a different currency and a different -numeric amount: - -[source,java] -.Example Currency Conversion -------------------------------------------------------------------- -MonetaryAmount inCHF =...; -CurrencyConversion conv = MonetaryConversions.getConversion("EUR"); -MonetaryAmount inEUR = inCHF.with(conv); -------------------------------------------------------------------- - -Also we can define the providers to be used for currency conversion by passing the provider names explicitly: -[source,java] -------------------------------------------------------------------------------- -CurrencyConversion conv = MonetaryConversions.getConversion("EUR", "ECB", "IMF"); -------------------------------------------------------------------------------- - -To cover also more complex usage scenarios we can also pass a +ConversionQuery+ with additional parameters for -conversion, e.g.: - -[source,java] -------------------------------------------------------------------- -MonetaryAmount inCHF =...; -CurrencyConversion conv = MonetaryConversions.getConversion(ConversionQueryBuilder.of() - .setProviders("CS", "ECB", "IMF") - .setTermCurrency("EUR") - .set(MonetaryAmount.class, inCHF, MonetaryAmount.class) - .set(LocalDate.of(2008, 1, 1)) - .setRateType(RateType.HISTORIC) - .set(StockExchange.NYSE) // custom type - .set("contractId", "AA-1234.2") - .build()); -MonetaryAmount inEUR = inCHF.with(conv); -------------------------------------------------------------------- - -:numbered!: - -== APPENDIX -[[Bibliography]] -=== Bibliography - -[[[Bitcoin]]] -http://bitcoin.org/en/ - -[[[ICU]]] -http://site.icu-project.org/ - -[[[ISO-4217]]] -http://www.iso.org/iso/home/standards/currency_codes.htm - -[[[ISO-20022]]] -http://www.iso20022.org - -[[[JadiraFramework]]] -The Jadira Framework adds Hibernate support for +MonetaryAmount+ if the JSR 354 API and an implementation are on the class path: http://jadira.sourceforge.net/project-info.html - -[[[JakartaBeanValidation]]] -Hibernate Validator supports any sub-type of +MonetaryAmount+ if the JSR 354 API and an implementation are on the class path: -https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-gettingstarted - -[[[SpringSupport]]] -Since release 4.2 the https://spring.io/projects/spring-framework[Spring Framework] supports JSR 354: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/format/number/money/package-summary.html - -[[[ZalandoJacksonBinding]]] -Zalando created Jackson Binding for JSR 354: https://github.com/zalando/jackson-datatype-money - -[[[JodaMoney]]] -http://www.joda.org/joda-money/ - -[[[GitHub]]] -https://javamoney.github.io/ - -[[[JSR354]]] -http://jcp.org/en/jsr/detail?id=354 - -[[[source]]] -Public Source Code Repository on GitHub: http://github.com/JavaMoney, - Branch/Tag matching updated PDR is {version} - -=== Links -* http://jcp.org/en/jsr/detail?id=35[JSR 354 on jcp.org] -* https://github.com/JavaMoney/[JavaMoney Project on GitHub] - ** https://github.com/JavaMoney/jsr354-api/[JSR 354 API GitHub Repository] - ** https://github.com/JavaMoney/jsr354-ri/[Moneta RI GitHub Repository] -* http://www.javapractices.com/topic/TopicAction.do?Id=13[Java Practices about Representing Money] -* http://blog.eisele.net/2011/08/working-with-money-in-java.html[Working with Money in Java] -* http://mindprod.com/jgloss/currency.html[Java currency] by Roedy Green, http://mindprod.com[Canadian Mind Products] -* http://www.eclipse.org/uomo/[UOMo Business], based on ICU4J and concepts by JScience Economics] -* http://site.icu-project.org/[ICU4J] Uses Number for all operations and internal storage in its Money type. -* http://moneydance.com/dev/apidoc/[MoneyDance API] -* http://javamoney.org[JavaMoney] is the Apache 2.0 licensed OSS project that evolved from JSR 354 development. It provides concrete implementations for currency conversion and mapping, advanced formatting, historic data access, regions and a set of financial calculations and formulas. -* http://www.joda.org/joda-money[Joda Money] can be referred to as an inspiration for API and design style. it is based on real-world use cases in an e-commerce application for airlines -* http://grails.org/plugin/currencies[Grails Currencies] uses BigDecimal as internal representation, but API only exposes Number in all Money operations like plus(), minus() or similar. -* http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money/[Why not to use BigDecimal for Money] -* http://de.wikipedia.org/wiki/M-Pesa[M-Pesa-Mobile Money] in Africa -* Currency Internationalization (i18n), Multiple Currencies and Foreign Exchange (FX). -* http://en.wikipedia.org/wiki/Japanese_units_of_measurement#Money: Discussion of internationalization of currencies, rounding, grouping and formatting, separators etc] -* http://speleotrove.com/decimal/ -* http://sourceforge.net/projects/oquote/ -* http://en.wikipedia.org/wiki/Karatsuba_algorithm[Karatsuba Algorithm] for Fast Big Decimal Multiplication - -=== Related Initiatives -* http://timeandmoney.sourceforge.net/ [Eric Evans Time and Money Library] -* http://bitcoinj.github.io/ [Bitcoin Java Client] diff --git a/src/main/asciidoc/images/highlighter.png b/src/main/asciidoc/images/highlighter.png deleted file mode 100644 index b31145948..000000000 Binary files a/src/main/asciidoc/images/highlighter.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/README b/src/main/asciidoc/images/icons/README deleted file mode 100644 index f12b2a730..000000000 --- a/src/main/asciidoc/images/icons/README +++ /dev/null @@ -1,5 +0,0 @@ -Replaced the plain DocBook XSL admonition icons with Jimmac's DocBook -icons (http://jimmac.musichall.cz/ikony.php3). I dropped transparency -from the Jimmac icons to get round MS IE and FOP PNG incompatibilies. - -Stuart Rackham diff --git a/src/main/asciidoc/images/icons/callouts/1.png b/src/main/asciidoc/images/icons/callouts/1.png deleted file mode 100644 index 7d473430b..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/1.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/10.png b/src/main/asciidoc/images/icons/callouts/10.png deleted file mode 100644 index 997bbc824..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/10.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/11.png b/src/main/asciidoc/images/icons/callouts/11.png deleted file mode 100644 index ce47dac3f..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/11.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/12.png b/src/main/asciidoc/images/icons/callouts/12.png deleted file mode 100644 index 31daf4e2f..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/12.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/13.png b/src/main/asciidoc/images/icons/callouts/13.png deleted file mode 100644 index 14021a89c..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/13.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/14.png b/src/main/asciidoc/images/icons/callouts/14.png deleted file mode 100644 index 64014b75f..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/14.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/15.png b/src/main/asciidoc/images/icons/callouts/15.png deleted file mode 100644 index 0d65765fc..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/15.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/2.png b/src/main/asciidoc/images/icons/callouts/2.png deleted file mode 100644 index 5d09341b2..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/2.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/3.png b/src/main/asciidoc/images/icons/callouts/3.png deleted file mode 100644 index ef7b70047..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/3.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/4.png b/src/main/asciidoc/images/icons/callouts/4.png deleted file mode 100644 index adb8364eb..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/4.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/5.png b/src/main/asciidoc/images/icons/callouts/5.png deleted file mode 100644 index 4d7eb4600..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/5.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/6.png b/src/main/asciidoc/images/icons/callouts/6.png deleted file mode 100644 index 0ba694af6..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/6.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/7.png b/src/main/asciidoc/images/icons/callouts/7.png deleted file mode 100644 index 472e96f8a..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/7.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/8.png b/src/main/asciidoc/images/icons/callouts/8.png deleted file mode 100644 index 5e60973c2..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/8.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/callouts/9.png b/src/main/asciidoc/images/icons/callouts/9.png deleted file mode 100644 index a0676d26c..000000000 Binary files a/src/main/asciidoc/images/icons/callouts/9.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/caution.png b/src/main/asciidoc/images/icons/caution.png deleted file mode 100644 index 9a8c515a1..000000000 Binary files a/src/main/asciidoc/images/icons/caution.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/example.png b/src/main/asciidoc/images/icons/example.png deleted file mode 100644 index 1199e864f..000000000 Binary files a/src/main/asciidoc/images/icons/example.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/home.png b/src/main/asciidoc/images/icons/home.png deleted file mode 100644 index 37a5231ba..000000000 Binary files a/src/main/asciidoc/images/icons/home.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/important.png b/src/main/asciidoc/images/icons/important.png deleted file mode 100644 index be685cc4e..000000000 Binary files a/src/main/asciidoc/images/icons/important.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/next.png b/src/main/asciidoc/images/icons/next.png deleted file mode 100644 index 64e126bdd..000000000 Binary files a/src/main/asciidoc/images/icons/next.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/note.png b/src/main/asciidoc/images/icons/note.png deleted file mode 100644 index 7c1f3e2fa..000000000 Binary files a/src/main/asciidoc/images/icons/note.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/prev.png b/src/main/asciidoc/images/icons/prev.png deleted file mode 100644 index 3e8f12fe2..000000000 Binary files a/src/main/asciidoc/images/icons/prev.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/tip.png b/src/main/asciidoc/images/icons/tip.png deleted file mode 100644 index f087c73b7..000000000 Binary files a/src/main/asciidoc/images/icons/tip.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/up.png b/src/main/asciidoc/images/icons/up.png deleted file mode 100644 index 2db1ce62f..000000000 Binary files a/src/main/asciidoc/images/icons/up.png and /dev/null differ diff --git a/src/main/asciidoc/images/icons/warning.png b/src/main/asciidoc/images/icons/warning.png deleted file mode 100644 index d41edb9ad..000000000 Binary files a/src/main/asciidoc/images/icons/warning.png and /dev/null differ diff --git a/src/main/asciidoc/images/javamoney_cup.jpg b/src/main/asciidoc/images/javamoney_cup.jpg deleted file mode 100644 index 077bd20d8..000000000 Binary files a/src/main/asciidoc/images/javamoney_cup.jpg and /dev/null differ diff --git a/src/main/asciidoc/images/smallnew.png b/src/main/asciidoc/images/smallnew.png deleted file mode 100644 index 411c2e178..000000000 Binary files a/src/main/asciidoc/images/smallnew.png and /dev/null differ diff --git a/src/main/asciidoc/images/spi.jpg b/src/main/asciidoc/images/spi.jpg deleted file mode 100644 index 2865e0d87..000000000 Binary files a/src/main/asciidoc/images/spi.jpg and /dev/null differ diff --git a/src/main/asciidoc/images/tiger.png b/src/main/asciidoc/images/tiger.png deleted file mode 100644 index 332b11f3a..000000000 Binary files a/src/main/asciidoc/images/tiger.png and /dev/null differ diff --git a/src/main/java/javax/money/AbstractContext.java b/src/main/java/javax/money/AbstractContext.java deleted file mode 100644 index 77341caef..000000000 --- a/src/main/java/javax/money/AbstractContext.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Represents a general context of data targeting an item of type {@code Q}. Contexts are used to add arbitrary - * data that cannot be be mapped in a standard way to the money API, e.g. use case or customer specific - * extensions or specialities.

- * Superclasses of this class must be final, immutable, serializable and thread-safe. - */ -@SuppressWarnings("unchecked") -public abstract class AbstractContext implements Serializable { - - private static final long serialVersionUID = 1L; - - /** - * Key for storing the target providers to be queried - */ - protected static final String KEY_PROVIDER = "provider"; - - - /** - * The data map containing all values. - */ - final Map data = new HashMap<>(); - - /** - * Private constructor, used by {@link AbstractContextBuilder}. - * - * @param builder the Builder. - */ - protected AbstractContext(AbstractContextBuilder builder) { - data.putAll(builder.data); - } - - /** - * Get the present keys of all entries with a given type, checking hereby if assignable. - * - * @param type The attribute type, not null. - * @return all present keys of attributes being assignable to the type, never null. - */ - public Set getKeys(Class type) { - return data.entrySet().stream().filter(val -> type.isAssignableFrom(val.getValue() - .getClass())).map(Map.Entry::getKey).collect(Collectors - .toSet()); - } - - /** - * Get the current attribute type. - * @param key the entry's key, not null - * @return the current attribute type, or null, if no such attribute exists. - */ - public Class getType(String key) { - Object val = this.data.get(key); - return val == null ? null : val.getClass(); - } - - - /** - * Access an attribute. - * - * @param type the attribute's type, not {@code null} - * @param key the attribute's key, not {@code null} - * @return the attribute value, or {@code null}. - */ - public T get(String key, Class type) { - Object value = this.data.get(key); - if (value != null && type.isAssignableFrom(value.getClass())) { - return (T) value; - } - return null; - } - - /** - * Access an attribute, hereby using the class name as key. - * - * @param type the type, not {@code null} - * @return the type attribute value, or {@code null}. - */ - public T get(Class type) { - return get(type.getName(), type); - } - - - /** - * Access a Long attribute. - * - * @param key the attribute's key, not null. - * @return the value, or null. - */ - public Long getLong(String key) { - return get(key, Long.class); - } - - - /** - * Access a Float attribute. - * - * @param key the attribute's key, not null. - * @return the value, or null. - */ - public Float getFloat(String key) { - return get(key, Float.class); - } - - /** - * Access an Integer attribute. - * - * @param key the attribute's key, not null. - * @return the value, or null. - */ - public Integer getInt(String key) { - return get(key, Integer.class); - } - - /** - * Access a Boolean attribute. - * - * @param key the attribute's key, not null. - * @return the value, or null. - */ - public Boolean getBoolean(String key) { - return get(key, Boolean.class); - } - - /** - * Access a Double attribute. - * - * @param key the attribute's key, not null. - * @return the value, or null. - */ - public Double getDouble(String key) { - return get(key, Double.class); - } - - /** - * Access a String attribute. - * - * @param key the attribute's key, not null. - * @return the value, or null. - */ - public String getText(String key) { - return get(key, String.class); - } - - /** - * Get the provider name of this context. - * - * @return the provider name, or null. - */ - public String getProviderName() { - return getText(KEY_PROVIDER); - } - - - /** - * Checks if the current instance has no attributes set. This is often the cases, when used in default cases. - * - * @return true, if no attributes are set. - */ - public boolean isEmpty() { - return this.data.isEmpty(); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return Objects.hash(data); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof AbstractContext) { - AbstractContext other = (AbstractContext) obj; - return Objects.equals(data, other.data); - } - return false; - } - - /* - * (non-Javadoc) - * - * @see Object#toString() - */ - @Override - public String toString() { - return getClass().getSimpleName() + " (\n" + data + ')'; - } -} diff --git a/src/main/java/javax/money/AbstractContextBuilder.java b/src/main/java/javax/money/AbstractContextBuilder.java deleted file mode 100644 index e4a84bc99..000000000 --- a/src/main/java/javax/money/AbstractContextBuilder.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.TreeMap; - -/** - * This interface defines the common generic parts of a query. Queries are used to pass complex parameters sets - * to lookup monetary artifacts, e.g. {@link MonetaryAmountFactory}, - * {@link javax.money.MonetaryRounding}, - * {@link javax.money.CurrencyUnit}, {@link javax.money.convert.ExchangeRateProvider} and {@link javax.money.convert - * .CurrencyConversion}. - *

- * Instances of this class are not thread-safe and not serializable. - */ -@SuppressWarnings({ "unchecked", "rawtypes" }) -public abstract class AbstractContextBuilder{ - - /** - * The data map containing all values. - */ - final Map data = new HashMap<>(); - - /** - * Apply all attributes on the given context. - * - * @param context the context to be applied, not null. - * @param overwriteDuplicates flag, if existing entries should be overwritten. - * @return this Builder, for chaining - */ - public B importContext(AbstractContext context, boolean overwriteDuplicates){ - for (Map.Entry en : context.data.entrySet()) { - if (overwriteDuplicates) { - this.data.put(en.getKey(), en.getValue()); - }else{ - this.data.putIfAbsent(en.getKey(), en.getValue()); - } - } - return (B) this; - } - - /** - * Apply all attributes on the given context, hereby existing entries are preserved. - * - * @param context the context to be applied, not null. - * @return this Builder, for chaining - * @see #importContext(AbstractContext, boolean) - */ - public B importContext(AbstractContext context){ - Objects.requireNonNull(context); - return importContext(context, false); - } - - /** - * Sets an Integer attribute. - * - * @param key the key, non null. - * @param value the value - * @return the Builder, for chaining. - */ - public B set(String key, int value) { - this.data.put(key, value); - return (B) this; - } - - - /** - * Sets an Boolean attribute. - * - * @param key the key, non null. - * @param value the value - * @return the Builder, for chaining. - */ - public B set(String key, boolean value) { - this.data.put(key, value); - return (B) this; - } - - - /** - * Sets an Long attribute. - * - * @param key the key, non null. - * @param value the value - * @return the Builder, for chaining. - */ - public B set(String key, long value) { - this.data.put(key, value); - return (B) this; - } - - - /** - * Sets an Float attribute. - * - * @param key the key, non null. - * @param value the value - * @return the Builder, for chaining. - */ - public B set(String key, float value) { - this.data.put(key, value); - return (B) this; - } - - /** - * Sets an Double attribute. - * - * @param key the key, non null. - * @param value the value - * @return the Builder, for chaining. - */ - public B set(String key, double value) { - this.data.put(key, value); - return (B) this; - } - - - /** - * Sets an Character attribute. - * - * @param key the key, non null. - * @param value the value - * @return the Builder, for chaining. - */ - public B set(String key, char value) { - this.data.put(key, value); - return (B) this; - } - - - /** - * Sets an attribute, using {@code attribute.getClass()} as attribute - * type and {@code attribute.getClass().getName()} as attribute - * name. - * - * @param value the attribute value, not null. - * @return this Builder, for chaining - */ - public B set(Object value) { - data.put(value.getClass().getName(), Objects.requireNonNull(value)); - return (B) this; - } - - /** - * Sets an attribute, using {@code attribute.getClass()} as attribute - * type. - * - * @param value the attribute value, not null. - * @param key the attribute's key, not {@code null} - * @return this Builder, for chaining - */ - public B set(String key, Object value) { - data.put(key, Objects.requireNonNull(value)); - return (B) this; - } - - /** - * Sets an attribute, using {@code attribute.getClass()} as attribute - * type. - * - * @param value the attribute value, not null. - * @param key the attribute's key, not {@code null} - * @return this Builder, for chaining - */ - public B set(Class key, T value) { - Object old = set(key.getName(), Objects.requireNonNull(value)); - if (old != null && old.getClass().isAssignableFrom(value.getClass())) { - return (B) old; - } - return (B) this; - } - - /** - * Sets the provider. - * - * @param provider the provider, not null. - * @return the Builder for chaining - */ - public B setProviderName(String provider) { - set(AbstractContext.KEY_PROVIDER, Objects.requireNonNull(provider)); - return (B) this; - } - - /** - * Removes an entry of a certain keys. This can be useful, when a context is initialized with another - * existing context, but only subset of the entries should be visible. For example {@code removeAttributes - * ("a", "b", "c")} removes all attributes named 'a','b' and 'c'. - * - * @param keys the keys - * @return this Builder, for chaining - */ - public B removeAttributes(String... keys) { - for (String key : keys) { - this.data.remove(key); - } - return (B) this; - } - - /** - * Creates a new {@link AbstractContext} with the data from this Builder - * instance. - * - * @return a new {@link AbstractContext}. never {@code null}. - */ - public abstract C build(); - - @Override - public String toString(){ - return getClass().getSimpleName() + " [attributes:\n" + new TreeMap<>(data).toString() + ']'; - } -} \ No newline at end of file diff --git a/src/main/java/javax/money/AbstractQuery.java b/src/main/java/javax/money/AbstractQuery.java deleted file mode 100644 index 03e4704de..000000000 --- a/src/main/java/javax/money/AbstractQuery.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.Collections; -import java.util.List; - -/** - * Represents a general context of data targeting an item of type {@code Q}. Contexts are used to add arbitrary - * data that cannot be be mapped in a standard way to the money API, e.g. use case or customer specific - * extensions or specialities.

- * Superclasses of this class must be final, immutable, serializable and thread-safe. - */ -public abstract class AbstractQuery extends AbstractContext { - - private static final long serialVersionUID = 5309190820845869327L; - - /** - * Key for storing the target providers to be queried - */ - protected static final String KEY_QUERY_PROVIDERS = "Query.providers"; - - /** - * Key name for the timestamp attribute. - */ - protected static final String KEY_QUERY_TIMESTAMP = "Query.timestamp"; - - /** - * Key name for the target type attribute. - */ - protected static final String KEY_QUERY_TARGET_TYPE = "Query.targetType"; - - - /** - * Constructor, using a builder. - * - * @param builder the builder, not null. - */ - protected AbstractQuery(@SuppressWarnings("rawtypes") AbstractQueryBuilder builder) { - super(builder); - } - - /** - * Returns the providers and their ordering to be considered. This information typically must be interpreted by the - * singleton SPI implementations, which are backing the singleton accessors. - * If the list returned is empty, the default provider list, - * determined by methods like {@code getDefaultProviderNames()} should be used. - * - * @return the ordered providers, never null. - */ - public List getProviderNames() { - - @SuppressWarnings("unchecked") List result = get(KEY_QUERY_PROVIDERS, List.class); - if (result == null) { - return Collections.emptyList(); - } - return result; - } - - /** - * Gets the target implementation type required. This can be used to explicitly acquire a specific implementation - * type and use a query to configure the instance or factory to be returned. - * - * @return this Builder for chaining. - */ - public Class getTargetType() { - return get(KEY_QUERY_TARGET_TYPE, Class.class); - } - -} diff --git a/src/main/java/javax/money/AbstractQueryBuilder.java b/src/main/java/javax/money/AbstractQueryBuilder.java deleted file mode 100644 index f6985807b..000000000 --- a/src/main/java/javax/money/AbstractQueryBuilder.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -/** - * This abstract class defines the common generic parts of a query. Queries are used to pass complex parameters sets - * to lookup monetary artifacts, e.g. {@link MonetaryAmountFactory}, - * {@link javax.money.MonetaryRounding}, - * {@link javax.money.CurrencyUnit}, {@link javax.money.convert.ExchangeRateProvider} and {@link javax.money.convert - * .CurrencyConversion}. - *

- * Instances of this class are not thread-safe and not serializable. - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractQueryBuilder - extends AbstractContextBuilder { - - /** - * Initializes the query builder, as a default query builder. - */ - public AbstractQueryBuilder() { - } - - - /** - * Set the providers to be considered. If not set explicitly the default ISO currencies as - * returned by {@link java.util.Currency} is used. - * - * @param providers the providers to use, not null. - * @return the query builder for chaining. - */ - public B setProviderNames(String... providers) { - return setProviderNames(Arrays.asList(providers)); - } - - /** - * Set the providers to be considered. If not set explicitly the default ISO currencies as - * returned by {@link java.util.Currency} is used. - * - * @param providers the providers to use, not null. - * @return the query builder for chaining. - */ - public B setProviderNames(List providers) { - Objects.requireNonNull(providers); - return set(AbstractQuery.KEY_QUERY_PROVIDERS, providers); - } - - /** - * Set the providers to be considered. If not set explicitly the default providers and the corresponding - * default ordering are used. - * - * @param providers the providers in order to use, not null. - * @return the query builder for chaining. - */ - public B set(List providers) { - return set(AbstractQuery.KEY_QUERY_PROVIDERS, providers); - } - - /** - * Simple override, that sets the provider as provider to use. - * - * @param provider the provider, not null. - * @return the query builder for chaining. - */ - @Override - public B setProviderName(String provider) { - return setProviderNames(provider); - } - - - /** - * Sets the target implementation type required. This can be used to explicitly acquire a specific - * implementation - * type and use a query to configure the instance or factory to be returned. - * - * @param type the target implementation type, not null. - * @return this query builder for chaining. - */ - @SuppressWarnings("unchecked") - public B setTargetType(Class type) { - Objects.requireNonNull(type); - set(AbstractQuery.KEY_QUERY_TARGET_TYPE, type); - return (B) this; - } - - /** - * Creates a new {@link AbstractQuery} with the data from this Builder - * instance. - * - * @return a new {@link AbstractQuery}. never {@code null}. - */ - @Override - public abstract C build(); - -} \ No newline at end of file diff --git a/src/main/java/javax/money/CurrencyContext.java b/src/main/java/javax/money/CurrencyContext.java deleted file mode 100644 index abf2d8730..000000000 --- a/src/main/java/javax/money/CurrencyContext.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.io.Serializable; - -/** - * This class models the attributable context of {@link javax.money.CurrencyUnit} instances. It - * provides information about - *

    - *
  • the provider that provided the instance (required) - *
  • the target timestamp / temporal unit - *
  • any other attributes, identified by the attribute type, e.g. regions, tenants etc. - *
- *

Instances of this class must be created using the {@link javax.money.CurrencyContextBuilder}. Typically the - * contexts are created and assigned by the classes that implement the {@link javax.money.spi.CurrencyProviderSpi}. - * The according implementation classes should document, which attributes are available.

- *

- * This class is immutable, serializable and thread-safe. - * - * @author Anatole Tresch - */ -public final class CurrencyContext extends AbstractContext implements Serializable{ - - private static final long serialVersionUID = 8450310852172607016L; - - - /** - * Constructor, used from the {@link javax.money.CurrencyContextBuilder}. - * - * @param builder the corresponding builder, not null. - */ - CurrencyContext(CurrencyContextBuilder builder){ - super(builder); - } - - - /** - * Allows to convert a instance into the corresponding {@link javax.money.CurrencyContextBuilder}, which allows - * to change the values and of another {@link javax.money.CurrencyContext} instance. - * - * @return a new Builder instance, preinitialized with the values from this instance. - */ - public CurrencyContextBuilder toBuilder(){ - return CurrencyContextBuilder.of(this); - } - - -} diff --git a/src/main/java/javax/money/CurrencyContextBuilder.java b/src/main/java/javax/money/CurrencyContextBuilder.java deleted file mode 100644 index f3c0bb7a6..000000000 --- a/src/main/java/javax/money/CurrencyContextBuilder.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.Objects; - -/** - * Builder class for creating new instances of {@link CurrencyContext} adding detailed information - * about a {@link CurrencyUnit} instance. Typically the - * contexts are created and assigned by the classes that implement the {@link javax.money.spi.CurrencyProviderSpi}. - * The according implementation classes should document, which attributes are available. - *

- * Note this class is NOT thread-safe. - * - * @see javax.money.CurrencyUnit#getContext() - */ -public final class CurrencyContextBuilder extends AbstractContextBuilder { - - /** - * Creates a new builder. - * - * @param provider the provider name, creating the corresponding {@link CurrencyUnit} containing - * the final {@link CurrencyContext} created by this builder, not null. - */ - private CurrencyContextBuilder(String provider) { - Objects.requireNonNull(provider); - setProviderName(provider); - } - - /** - * Creates a new builder. - * - * @param context the {@link javax.money.CurrencyContext} to be used for initializing this builder. - */ - private CurrencyContextBuilder(CurrencyContext context) { - Objects.requireNonNull(context); - importContext(context); - } - - /** - * Creates a new instance of {@link javax.money.CurrencyContext}. - * - * @return a new {@link javax.money.CurrencyContext} instance. - */ - @Override - public CurrencyContext build() { - return new CurrencyContext(this); - } - - /** - * Creates a new builder. - * - * @param provider the provider name, creating the corresponding {@link CurrencyUnit} containing - * the final {@link CurrencyContext} created by this builder, not null. - * @return a new {@link javax.money.CurrencyContextBuilder} instance, never null. - */ - public static CurrencyContextBuilder of(String provider) { - return new CurrencyContextBuilder(provider); - } - - /** - * Creates a new builder. - * - * @param context the {@link javax.money.CurrencyContext} to be used for initializing this builder. - * @return a new {@link javax.money.CurrencyContextBuilder} instance, never null. - */ - public static CurrencyContextBuilder of(CurrencyContext context) { - return new CurrencyContextBuilder(context); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/CurrencyQuery.java b/src/main/java/javax/money/CurrencyQuery.java deleted file mode 100644 index 86f4d82fb..000000000 --- a/src/main/java/javax/money/CurrencyQuery.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Collections; -import java.util.Locale; - -/** - * This class models a query for accessing instances of {@link CurrencyUnit}. It - * provides information such as - *

    - *
  • the providers that may provide {@link CurrencyUnit} instances - *
  • any other attributes, identified by the attribute type, e.g. regions, tenants, - * a target timestamp / temporal unit, when the {@link CurrencyUnit} instances should be valid, etc. - *
- * The effective attributes supported are only determined by the implementations of {@link javax.money.spi - * .CurrencyProviderSpi}. - *

- * This class is immutable, serializable and thread-safe. - * - * @author Anatole Tresch - */ -@SuppressWarnings("unchecked") -public final class CurrencyQuery extends AbstractQuery implements Serializable { - - private static final long serialVersionUID = -5117949582074719190L; - - /** - * Key for storing a countries to be queried. - */ - static final String KEY_QUERY_COUNTRIES = "Query.countries"; - - /** - * Key for storing a target literal currency codes to be queried. - */ - static final String KEY_QUERY_CURRENCY_CODES = "Query.currencyCodes"; - - /** - * Key for storing a target numeric currency codes to be queried. - */ - static final String KEY_QUERY_NUMERIC_CODES = "Query.numericCodes"; - - /** - * Constructor, used from the Builder. - * - * @param builder the corresponding {@link javax.money.CurrencyQueryBuilder}, not null. - */ - CurrencyQuery(CurrencyQueryBuilder builder) { - super(builder); - } - - /** - * Returns the target locales. - * - * @return the target locales, never null. - */ - public Collection getCountries() { - Collection result = get(KEY_QUERY_COUNTRIES, Collection.class); - if (result == null) { - return Collections.emptySet(); - } - return result; - } - - /** - * Gets the currency codes, or the regular expression to select codes. - * - * @return the target currency codes or the regular expression, never null. - */ - public Collection getCurrencyCodes() { - Collection result = get(KEY_QUERY_CURRENCY_CODES, Collection.class); - if (result == null) { - return Collections.emptySet(); - } - return result; - } - - /** - * Gets the numeric codes. Setting it to -1 search for currencies that have no numeric code. - * - * @return the target numeric codes, never null. - */ - public Collection getNumericCodes() { - Collection result = get(KEY_QUERY_NUMERIC_CODES, Collection.class); - if (result == null) { - return Collections.emptySet(); - } - return result; - } - - /** - * Creates a new builder instances, initialized with the data from this one. - * - * @return a new {@link MonetaryAmountFactoryQueryBuilder} instance, never null. - */ - public CurrencyQueryBuilder toBuilder() { - return CurrencyQueryBuilder.of(this); - } - -} diff --git a/src/main/java/javax/money/CurrencyQueryBuilder.java b/src/main/java/javax/money/CurrencyQueryBuilder.java deleted file mode 100644 index f0366dd35..000000000 --- a/src/main/java/javax/money/CurrencyQueryBuilder.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.Arrays; -import java.util.Locale; -import java.util.Objects; -import java.util.stream.Collectors; - - -/** - * Builder for queries for accessing {@link javax.money.CurrencyUnit} instances. If not properties are set the - * query should - * returns - * the default currencies. Similarly if no provider is set explicitly the default ISO currencies as - * returned by {@link java.util.Currency} should be returned. - *

- * Note this class is NOT thread-safe. - */ -public final class CurrencyQueryBuilder extends AbstractQueryBuilder { - - /** - * Default constructor. - */ - private CurrencyQueryBuilder() { - } - - /** - * Creates a new instance of {@link javax.money.CurrencyQueryBuilder}. - * - * @param currencyQuery {@link javax.money.CurrencyQuery} used for initializing this builder. - */ - private CurrencyQueryBuilder(CurrencyQuery currencyQuery) { - Objects.requireNonNull(currencyQuery); - importContext(currencyQuery); - } - - /** - * Sets the country for which currencies should be requested. - * - * @param countries The ISO countries. - * @return the query for chaining. - */ - public CurrencyQueryBuilder setCountries(Locale... countries) { - return set(CurrencyQuery.KEY_QUERY_COUNTRIES, Arrays.asList(countries)); - } - - /** - * Sets the currency code, or the regular expression to select codes. - * - * @param codes the currency codes or code expressions, not null. - * @return the query for chaining. - */ - public CurrencyQueryBuilder setCurrencyCodes(String... codes) { - return set(CurrencyQuery.KEY_QUERY_CURRENCY_CODES, Arrays.asList(codes)); - } - - /** - * Set the numeric code. Setting it to -1 search for currencies that have no numeric code. - * - * @param codes the numeric codes. - * @return the query for chaining. - */ - public CurrencyQueryBuilder setNumericCodes(int... codes) { - return set(CurrencyQuery.KEY_QUERY_NUMERIC_CODES, - Arrays.stream(codes).boxed().collect(Collectors.toList())); - } - - /** - * Creates a new instance of {@link javax.money.CurrencyQuery}. - * - * @return a new {@link javax.money.CurrencyQuery} instance, never null. - */ - public CurrencyQuery build() { - return new CurrencyQuery(this); - } - - /** - * Creates a new instance of {@link javax.money.CurrencyQueryBuilder}. - * - * @return a new {@link javax.money.CurrencyQueryBuilder} instance, never null. - */ - public static CurrencyQueryBuilder of() { - return new CurrencyQueryBuilder(); - } - - /** - * Creates a new instance of {@link javax.money.CurrencyQueryBuilder}. - * - * @param currencyQuery {@link javax.money.CurrencyQuery} used for initializing this builder. - * @return a new {@link javax.money.CurrencyQueryBuilder} instance, never null. - */ - public static CurrencyQueryBuilder of(CurrencyQuery currencyQuery) { - return new CurrencyQueryBuilder(currencyQuery); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/CurrencySupplier.java b/src/main/java/javax/money/CurrencySupplier.java deleted file mode 100644 index 886c4250b..000000000 --- a/src/main/java/javax/money/CurrencySupplier.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - - -/** - * Represents a supplier of {@link CurrencyUnit}-valued results. This is the - * {@link CurrencyUnit}-producing specialization of {@code Supplier} (as in Java 8). - * - *

- * There is no requirement that a distinct result be returned each time the - * supplier is invoked. - * - *

- * This is a functional interface whose - * functional method is {@link #getCurrency()}. - * This class does not extend {@link java.util.function.Supplier} since {@link javax.money.MonetaryAmount} implements - * both supplier interfaces, {@link javax.money.NumberSupplier} and {@link javax.money.CurrencySupplier}, - * which will lead - * to method name conflicts. - *

- * - * @author Werner Keil - * @version 0.5 - * @since 0.8 - * @see java.util.function.Supplier - */ -@FunctionalInterface -public interface CurrencySupplier { - - /** - * Gets the corresponding {@link javax.money.CurrencyUnit}. - * - * @return the corresponding {@link javax.money.CurrencyUnit}, not null. - */ - CurrencyUnit getCurrency(); -} \ No newline at end of file diff --git a/src/main/java/javax/money/CurrencyUnit.java b/src/main/java/javax/money/CurrencyUnit.java deleted file mode 100644 index bbda28093..000000000 --- a/src/main/java/javax/money/CurrencyUnit.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -/** - * A unit of currency. - *

- * This interface represents a unit of currency such as the British Pound, Euro, - * US Dollar, Bitcoin or other. It provides interoperability between different - * implementations. - *

- * Currencies can be distinguished by separate {@link #getCurrencyCode()} codes, - * similar to {@link java.util.Currency}. - *

Implementation specification

- * Implementation of this class - *
    - *
  • are required to implement {@code equals/hashCode} considering the - * concrete implementation type and currency code.
  • - *
  • are required to be thread-safe
  • - *
  • are required to be immutable
  • - *
  • are required to be comparable
  • - *
  • should be serializable (on platforms providing serialization).
  • - *
- * - * @author Werner Keil - * @author Stephen Colebourne - * @author Anatole Tresch - * - * @version 1.0 - * - * @see Wikipedia: Currency - */ -public interface CurrencyUnit extends Comparable{ - - /** - * Gets the unique currency code, the effective code depends on the - * currency. - *

- * Since each currency is identified by this code, the currency code is - * required to be defined for every {@link CurrencyUnit} and not - * {@code null} or empty. - *

- * For ISO codes the 3-letter ISO code should be returned. For non ISO - * currencies no constraints are defined. - * - * @return the currency code, never {@code null}. For ISO-4217 this this - * will be the three letter ISO-4217 code. However, alternate - * currencies can have different codes. Also there is no constraint - * about the formatting of alternate codes, despite the fact that - * the currency codes must be unique. - */ - String getCurrencyCode(); - - /** - * Gets a numeric currency code. within the ISO-4217 name space, this equals - * to the ISO numeric code. In other currency name spaces this number may be - * different, or even undefined (-1). - *

- * The numeric code is an optional alternative to the standard currency - * code. If defined, the numeric code is required to be unique. - *

- * This method matches the API of {@link java.util.Currency}. - * - * @return the numeric currency code - */ - int getNumericCode(); - - /** - * Gets the number of fractional digits typically used by this currency. - *

- * Different currencies have different numbers of fractional digits by - * default. For example, 'GBP' has 2 fractional digits, but 'JPY' has zero. - * virtual currencies or those with no applicable fractional are indicated - * by -1. - *

- * This method matches the API of {@link java.util.Currency}. - * - * @return the fractional digits, from 0 to 9 (normally 0, 2 or 3), or 0 for - * pseudo-currencies. - * - */ - int getDefaultFractionDigits(); - - /** - * Returns the {@link javax.money.CurrencyContext} of a currency. This context contains additional information - * about the type and capabilities of a CurrencyUnit, e.g. its provider and more. - * @return the currency's context, never null. - */ - CurrencyContext getContext(); -} diff --git a/src/main/java/javax/money/DefaultMonetaryCurrenciesSingletonSpi.java b/src/main/java/javax/money/DefaultMonetaryCurrenciesSingletonSpi.java deleted file mode 100644 index 4f40bbeb9..000000000 --- a/src/main/java/javax/money/DefaultMonetaryCurrenciesSingletonSpi.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import javax.money.spi.Bootstrap; -import javax.money.spi.CurrencyProviderSpi; -import javax.money.spi.MonetaryCurrenciesSingletonSpi; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Factory singleton for {@link CurrencyUnit} instances as provided by the - * different registered {@link javax.money.spi.CurrencyProviderSpi} instances. - *

- * This class is thread safe. - * - * @author Anatole Tresch - * @version 0.8 - */ -final class DefaultMonetaryCurrenciesSingletonSpi implements MonetaryCurrenciesSingletonSpi { - - @Override - public Set getCurrencies(CurrencyQuery query) { - Set result = new HashSet<>(); - for (CurrencyProviderSpi spi : Bootstrap.getServices(CurrencyProviderSpi.class)) { - try { - result.addAll(spi.getCurrencies(query)); - } catch (Exception e) { - Logger.getLogger(DefaultMonetaryCurrenciesSingletonSpi.class.getName()) - .log(Level.SEVERE, "Error loading currency provider names for " + spi.getClass().getName(), - e); - } - } - return result; - } - - /** - * This default implementation simply returns all providers defined in arbitrary order. - * - * @return the default provider chain, never null. - */ - @Override - public List getDefaultProviderChain() { - List list = new ArrayList<>(getProviderNames()); - Collections.sort(list); - return list; - } - - /** - * Get the names of the currently loaded providers. - * - * @return the names of the currently loaded providers, never null. - */ - @Override - public Set getProviderNames() { - Set result = new HashSet<>(); - for (CurrencyProviderSpi spi : Bootstrap.getServices(CurrencyProviderSpi.class)) { - try { - result.add(spi.getProviderName()); - } catch (Exception e) { - Logger.getLogger(DefaultMonetaryCurrenciesSingletonSpi.class.getName()) - .log(Level.SEVERE, "Error loading currency provider names for " + spi.getClass().getName(), - e); - } - } - return result; - } - -} diff --git a/src/main/java/javax/money/DefaultMonetaryRoundingsSingletonSpi.java b/src/main/java/javax/money/DefaultMonetaryRoundingsSingletonSpi.java deleted file mode 100644 index 5ef5f4182..000000000 --- a/src/main/java/javax/money/DefaultMonetaryRoundingsSingletonSpi.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import javax.money.spi.Bootstrap; -import javax.money.spi.MonetaryRoundingsSingletonSpi; -import javax.money.spi.RoundingProviderSpi; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * This class models the accessor for rounding instances, modeled as - * {@link javax.money.MonetaryOperator}. - *

- * This class is thread-safe. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public final class DefaultMonetaryRoundingsSingletonSpi implements MonetaryRoundingsSingletonSpi { - - /** - * An adaptive rounding instance that transparently looks up the correct - * rounding. - */ - private static final MonetaryRounding DEFAULT_ROUNDING = new DefaultCurrencyRounding(); - - /** - * Creates an rounding instance using {@link java.math.RoundingMode#UP} rounding. - * - * @return the corresponding {@link MonetaryOperator} implementing the - * rounding. - * @throws MonetaryException if no such rounding could be evaluated. - */ - public RoundingQueryBuilder createRoundingQueryBuilder() { - throw new IllegalStateException("No MonetaryRoundingsSingletonSpi registered."); - } - - /** - * Get the default rounding, which delegates rounding dynamically depending on the current currency. - * - * @return the default rounding, never null. - */ - @Override - public MonetaryRounding getDefaultRounding() { - return DEFAULT_ROUNDING; - } - - - /** - * Query all roundings matching the given {@link RoundingQuery}. - * - * @param query the rounding query, not null. - * @return the collection found, not null. - */ - @Override - public Collection getRoundings(RoundingQuery query) { - List result = new ArrayList<>(); - Collection providerNames = query.getProviderNames(); - if (providerNames == null || providerNames.isEmpty()) { - providerNames = getDefaultProviderChain(); - } - for (String providerName : providerNames) { - Bootstrap.getServices(RoundingProviderSpi.class).stream() - .filter(prov -> providerName.equals(prov.getProviderName())).forEach(prov -> { - try { - MonetaryRounding r = prov.getRounding(query); - if (r != null) { - result.add(r); - } - } catch (Exception e) { - Logger.getLogger(DefaultMonetaryRoundingsSingletonSpi.class.getName()) - .log(Level.SEVERE, "Error loading RoundingProviderSpi from provider: " + prov, e); - } - }); - } - return result; - } - - /** - * Get the names of all current registered providers. - * - * @return the names of all current registered providers, never null. - */ - @Override - public Set getProviderNames() { - Set result = new HashSet<>(); - for (RoundingProviderSpi prov : Bootstrap.getServices(RoundingProviderSpi.class)) { - try { - result.add(prov.getProviderName()); - } catch (Exception e) { - Logger.getLogger(Monetary.class.getName()) - .log(Level.SEVERE, "Error loading RoundingProviderSpi from provider: " + prov, e); - } - } - return result; - } - - /** - * Get the default providers list to be used. - * - * @return the default provider list and ordering, not null. - */ - @Override - public List getDefaultProviderChain() { - List result = new ArrayList<>(Monetary.getRoundingProviderNames()); - Collections.sort(result); - return result; - } - - /** - * Allows to access the identifiers of the current defined roundings. - * - * @param providers the providers and ordering to be used. By default providers and ordering as defined in - * #getDefaultProviders is used, not null. - * @return the set of custom rounding ids, never {@code null}. - */ - @Override - public Set getRoundingNames(String... providers) { - Set result = new HashSet<>(); - String[] providerNames = providers; - if (providerNames.length == 0) { - providerNames = Monetary.getDefaultRoundingProviderChain().toArray(new String[Monetary.getDefaultRoundingProviderChain().size()]); - } - for (String providerName : providerNames) { - for (RoundingProviderSpi prov : Bootstrap.getServices(RoundingProviderSpi.class)) { - try { - if (prov.getProviderName().equals(providerName) || prov.getProviderName().matches(providerName)) { - result.addAll(prov.getRoundingNames()); - } - } catch (Exception e) { - Logger.getLogger(DefaultMonetaryRoundingsSingletonSpi.class.getName()) - .log(Level.SEVERE, "Error loading RoundingProviderSpi from provider: " + prov, e); - } - } - } - return result; - } - - /** - * Default Rounding that rounds a {@link MonetaryAmount} based on the - * amount's {@link CurrencyUnit}. - * - * @author Anatole Tresch - */ - private static final class DefaultCurrencyRounding implements MonetaryRounding, Serializable { - - private static final long serialVersionUID = 8641545296538357839L; - - private static final RoundingContext ROUNDING_CONTEXT = RoundingContextBuilder.of("default", "default").build(); - - @Override - public MonetaryAmount apply(MonetaryAmount amount) { - MonetaryRounding r = Monetary.getRounding(amount.getCurrency()); - return r.apply(amount); - } - - @Override - public RoundingContext getRoundingContext() { - return ROUNDING_CONTEXT; - } - } - -} diff --git a/src/main/java/javax/money/Monetary.java b/src/main/java/javax/money/Monetary.java deleted file mode 100644 index c80f14054..000000000 --- a/src/main/java/javax/money/Monetary.java +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import javax.money.spi.*; - -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.Optional; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Factory singleton for {@link CurrencyUnit}, {@link javax.money.MonetaryAmount} and - * {@link javax.money.MonetaryRounding} instances as provided by the - * different registered SPI instances. - *

- * This class is thread safe. - *

- * - * @author Anatole Tresch - */ -public final class Monetary { - /** - * The used {@link javax.money.spi.MonetaryCurrenciesSingletonSpi} instance. - * - * @return the used {@link javax.money.spi.MonetaryCurrenciesSingletonSpi} instance, - * never {@code null} - */ - private static MonetaryCurrenciesSingletonSpi monetaryCurrenciesSingletonSpi() { - try { - return Optional.ofNullable(Bootstrap - .getService(MonetaryCurrenciesSingletonSpi.class)).orElseGet( - DefaultMonetaryCurrenciesSingletonSpi::new); - } catch (Exception e) { - Logger.getLogger(Monetary.class.getName()) - .log(Level.WARNING, "Failed to load MonetaryCurrenciesSingletonSpi, using default.", e); - return new DefaultMonetaryCurrenciesSingletonSpi(); - } - } - - /** - * The used {@link javax.money.spi.MonetaryAmountsSingletonSpi} instance. - */ - private static MonetaryAmountsSingletonSpi monetaryAmountsSingletonSpi() { - try { - return Bootstrap.getService(MonetaryAmountsSingletonSpi.class); - } catch (Exception e) { - Logger.getLogger(Monetary.class.getName()) - .log(Level.SEVERE, "Failed to load MonetaryAmountsSingletonSpi.", e); - return null; - } - } - - /** - * The used {@link javax.money.spi.MonetaryAmountsSingletonSpi} instance. - */ - private static MonetaryAmountsSingletonQuerySpi monetaryAmountsSingletonQuerySpi() { - try { - return Bootstrap.getService(MonetaryAmountsSingletonQuerySpi.class); - } catch (Exception e) { - Logger.getLogger(Monetary.class.getName()).log(Level.SEVERE, "Failed to load " + - "MonetaryAmountsSingletonQuerySpi, " + - "query functionality will not be " + - "available.", e); - return null; - } - } - - /** - * The used {@link javax.money.spi.MonetaryCurrenciesSingletonSpi} instance. - * - * @return the used {@link javax.money.spi.MonetaryCurrenciesSingletonSpi} instance, - * never {@code null} - */ - private static MonetaryRoundingsSingletonSpi monetaryRoundingsSingletonSpi() { - try { - return Optional.ofNullable(Bootstrap - .getService(MonetaryRoundingsSingletonSpi.class)) - .orElseGet(DefaultMonetaryRoundingsSingletonSpi::new); - } catch (Exception e) { - Logger.getLogger(Monetary.class.getName()) - .log(Level.SEVERE, "Failed to load MonetaryCurrenciesSingletonSpi, using default.", e); - return new DefaultMonetaryRoundingsSingletonSpi(); - } - } - - /** - * Private singletons constructor. - */ - private Monetary() { - } - - /** - * Allows to access the names of the current registered providers. - * - * @return the set of provider names, never {@code null}. - */ - public static Set getRoundingProviderNames() { - return monetaryRoundingsSingletonSpi() - .getProviderNames(); - } - - /** - * Allows to access the default providers chain used if no provider chain was passed explicitly.. - * - * @return the chained list of provider names, never {@code null}. - */ - public static List getDefaultRoundingProviderChain() { - return monetaryRoundingsSingletonSpi() - .getDefaultProviderChain(); - } - - /** - * Creates a rounding that can be added as {@link MonetaryOperator} to - * chained calculations. The instance will lookup the concrete - * {@link MonetaryOperator} instance from the {@link Monetary} - * based on the input {@link MonetaryAmount}'s {@link CurrencyUnit}. - * - * @return the (shared) default rounding instance. - */ - public static MonetaryRounding getDefaultRounding() { - return monetaryRoundingsSingletonSpi() - .getDefaultRounding(); - } - - /** - * Creates an {@link MonetaryOperator} for rounding {@link MonetaryAmount} - * instances given a currency. - * - * @param currencyUnit The currency, which determines the required scale. As - * {@link java.math.RoundingMode}, by default, {@link java.math.RoundingMode#HALF_UP} - * is used. - * @param providers the providers and ordering to be used. By default providers and ordering as defined in - * #getDefaultProviders is used. - * @return a new instance {@link MonetaryOperator} implementing the - * rounding, never {@code null}. - */ - public static MonetaryRounding getRounding(CurrencyUnit currencyUnit, String... providers) { - return monetaryRoundingsSingletonSpi() - .getRounding(currencyUnit, providers); - } - - /** - * Access an {@link MonetaryOperator} for custom rounding - * {@link MonetaryAmount} instances. - * - * @param roundingName The rounding identifier. - * @param providers the providers and ordering to be used. By default providers and ordering as defined in - * #getDefaultProviders is used. - * @return the corresponding {@link MonetaryOperator} implementing the - * rounding, never {@code null}. - * @throws IllegalArgumentException if no such rounding is registered using a - * {@link javax.money.spi.RoundingProviderSpi} instance. - */ - public static MonetaryRounding getRounding(String roundingName, String... providers) { - return monetaryRoundingsSingletonSpi() - .getRounding(roundingName, providers); - } - - /** - * Access a {@link MonetaryRounding} using a possibly complex query. - * - * @param roundingQuery The {@link javax.money.RoundingQuery} that may contains arbitrary parameters to be - * evaluated. - * @return the corresponding {@link javax.money.MonetaryRounding}, never {@code null}. - * @throws IllegalArgumentException if no such rounding is registered using a - * {@link javax.money.spi.RoundingProviderSpi} instance. - */ - public static MonetaryRounding getRounding(RoundingQuery roundingQuery) { - return monetaryRoundingsSingletonSpi() - .getRounding(roundingQuery); - } - - /** - * Checks if a {@link MonetaryRounding} is available given a roundingId. - * - * @param roundingName The rounding identifier. - * @param providers the providers and ordering to be used. By default providers and ordering as defined in - * #getDefaultProviders is used. - * @return true, if a corresponding {@link javax.money.MonetaryRounding} is available. - * @throws IllegalArgumentException if no such rounding is registered using a - * {@link javax.money.spi.RoundingProviderSpi} instance. - */ - public static boolean isRoundingAvailable(String roundingName, String... providers) { - return monetaryRoundingsSingletonSpi() - .isRoundingAvailable(roundingName, providers); - } - - /** - * Checks if a {@link MonetaryRounding} is available given a roundingId. - * - * @param currencyUnit The currency, which determines the required scale. As {@link java.math.RoundingMode}, - * by default, {@link java.math.RoundingMode#HALF_UP} is used. - * @param providers the providers and ordering to be used. By default providers and ordering as defined in - * #getDefaultProviders is used. - * @return true, if a corresponding {@link javax.money.MonetaryRounding} is available. - * @throws IllegalArgumentException if no such rounding is registered using a - * {@link javax.money.spi.RoundingProviderSpi} instance. - */ - public static boolean isRoundingAvailable(CurrencyUnit currencyUnit, String... providers) { - return monetaryRoundingsSingletonSpi() - .isRoundingAvailable(currencyUnit, providers); - } - - /** - * Checks if a {@link MonetaryRounding} matching the query is available. - * - * @param roundingQuery The {@link javax.money.RoundingQuery} that may contains arbitrary parameters to be - * evaluated. - * @return true, if a corresponding {@link javax.money.MonetaryRounding} is available. - * @throws IllegalArgumentException if no such rounding is registered using a - * {@link javax.money.spi.RoundingProviderSpi} instance. - */ - public static boolean isRoundingAvailable(RoundingQuery roundingQuery) { - return monetaryRoundingsSingletonSpi() - .isRoundingAvailable(roundingQuery); - } - - - /** - * Access multiple {@link MonetaryRounding} instances using a possibly complex query - * - * @param roundingQuery The {@link javax.money.RoundingQuery} that may contains arbitrary parameters to be - * evaluated. - * @return all {@link javax.money.MonetaryRounding} instances matching the query, never {@code null}. - */ - public static Collection getRoundings(RoundingQuery roundingQuery) { - return monetaryRoundingsSingletonSpi() - .getRoundings(roundingQuery); - } - - - /** - * Allows to access the names of the current defined roundings. - * - * @param providers the providers and ordering to be used. By default providers and ordering as defined in - * #getDefaultProviders is used. - * @return the set of custom rounding ids, never {@code null}. - */ - public static Set getRoundingNames(String... providers) { - return monetaryRoundingsSingletonSpi() - .getRoundingNames(providers); - } - - /** - * Access an {@link MonetaryAmountFactory} for the given {@link MonetaryAmount} implementation - * type. - * - * @param amountType {@link MonetaryAmount} implementation type, nor {@code null}. - * @return the corresponding {@link MonetaryAmountFactory}, never {@code null}. - * @throws MonetaryException if no {@link MonetaryAmountFactory} targeting the given {@link MonetaryAmount} - * implementation class is registered. - */ - public static MonetaryAmountFactory getAmountFactory(Class amountType) { - MonetaryAmountsSingletonSpi spi = Optional.ofNullable(monetaryAmountsSingletonSpi()) - .orElseThrow(() -> new MonetaryException("No MonetaryAmountsSingletonSpi loaded.")); - MonetaryAmountFactory factory = spi.getAmountFactory(amountType); - return Optional.ofNullable(factory).orElseThrow( - () -> new MonetaryException("No AmountFactory available for type: " + amountType.getName())); - } - - /** - * Access the default {@link MonetaryAmountFactory} as defined by - * {@link javax.money.spi.MonetaryAmountsSingletonSpi#getDefaultAmountFactory()}. - * - * @return the {@link MonetaryAmountFactory} corresponding to default amount type, - * never {@code null}. - * @throws MonetaryException if no {@link MonetaryAmountFactory} targeting the default amount type - * implementation class is registered. - */ - public static MonetaryAmountFactory getDefaultAmountFactory() { - return Optional.ofNullable(monetaryAmountsSingletonSpi()) - .orElseThrow(() -> new MonetaryException("No MonetaryAmountsSingletonSpi loaded.")) - .getDefaultAmountFactory(); - } - - /** - * Access all currently available {@link MonetaryAmount} implementation classes that are - * accessible from this {@link MonetaryAmount} singleton. - * - * @return all currently available {@link MonetaryAmount} implementation classes that have - * corresponding {@link MonetaryAmountFactory} instances provided, never {@code null} - */ - public static Collection> getAmountFactories() { - return Optional.ofNullable(monetaryAmountsSingletonSpi()) - .orElseThrow(() -> new MonetaryException("No MonetaryAmountsSingletonSpi loaded.")) - .getAmountFactories(); - } - - /** - * Access all currently available {@link MonetaryAmount} implementation classes that are - * accessible from this {@link MonetaryAmount} singleton. - * - * @return all currently available {@link MonetaryAmount} implementation classes that have - * corresponding {@link MonetaryAmountFactory} instances provided, never {@code null} - */ - public static Collection> getAmountTypes() { - return Optional.ofNullable(monetaryAmountsSingletonSpi()) - .orElseThrow(() -> new MonetaryException("No MonetaryAmountsSingletonSpi loaded.")).getAmountTypes(); - } - - /** - * Access the default {@link MonetaryAmount} implementation class that is - * accessible from this {@link MonetaryAmount} singleton. - * - * @return all current default {@link MonetaryAmount} implementation class, never {@code null} - */ - public static Class getDefaultAmountType() { - return Optional.ofNullable(monetaryAmountsSingletonSpi()) - .orElseThrow(() -> new MonetaryException("No MonetaryAmountsSingletonSpi loaded.")) - .getDefaultAmountType(); - } - - /** - * Executes the query and returns the factory found, if there is only one factory. - * If multiple factories match the query, one is selected. - * - * @param query the factory query, not null. - * @return the factory found, or null. - */ - @SuppressWarnings("rawtypes") - public static MonetaryAmountFactory getAmountFactory(MonetaryAmountFactoryQuery query) { - return Optional.ofNullable(monetaryAmountsSingletonQuerySpi()).orElseThrow(() -> new MonetaryException( - "No MonetaryAmountsSingletonQuerySpi loaded, query functionality is not available.")) - .getAmountFactory(query); - } - - /** - * Returns all factory instances that match the query. - * - * @param query the factory query, not null. - * @return the instances found, never null. - */ - public static Collection> getAmountFactories(MonetaryAmountFactoryQuery query) { - return Optional.ofNullable(monetaryAmountsSingletonQuerySpi()).orElseThrow(() -> new MonetaryException( - "No MonetaryAmountsSingletonQuerySpi loaded, query functionality is not available.")) - .getAmountFactories(query); - } - - /** - * Allows to check if any of the getXXX methods return non empty/non null results of {@link javax.money - * .MonetaryAmountFactory}. - * - * @param query the factory query, not null. - * @return true, if at least one {@link MonetaryAmountFactory} matches the query. - */ - public static boolean isAvailable(MonetaryAmountFactoryQuery query) { - return Optional.ofNullable(monetaryAmountsSingletonQuerySpi()).orElseThrow(() -> new MonetaryException( - "No MonetaryAmountsSingletonQuerySpi loaded, query functionality is not available.")) - .isAvailable(query); - } - - /** - * Access a new instance based on the currency code. Currencies are - * available as provided by {@link CurrencyProviderSpi} instances registered - * with the {@link javax.money.spi.Bootstrap}. - * - * @param currencyCode the ISO currency code, not {@code null}. - * @param providers the (optional) specification of providers to consider. - * @return the corresponding {@link CurrencyUnit} instance. - * @throws UnknownCurrencyException if no such currency exists. - */ - public static CurrencyUnit getCurrency(String currencyCode, String... providers) { - return monetaryCurrenciesSingletonSpi() - .getCurrency(currencyCode, providers); - } - - /** - * Access a new instance based on the {@link Locale}. Currencies are - * available as provided by {@link CurrencyProviderSpi} instances registered - * with the {@link javax.money.spi.Bootstrap}. - * - * @param locale the target {@link Locale}, typically representing an ISO - * country, not {@code null}. - * @param providers the (optional) specification of providers to consider. - * @return the corresponding {@link CurrencyUnit} instance. - * @throws UnknownCurrencyException if no such currency exists. - */ - public static CurrencyUnit getCurrency(Locale locale, String... providers) { - return monetaryCurrenciesSingletonSpi() - .getCurrency(locale, providers); - } - - /** - * Access a new instance based on the {@link Locale}. Currencies are - * available as provided by {@link CurrencyProviderSpi} instances registered - * with the {@link javax.money.spi.Bootstrap}. - * - * @param locale the target {@link Locale}, typically representing an ISO - * country, not {@code null}. - * @param providers the (optional) specification of providers to consider. - * @return the corresponding {@link CurrencyUnit} instance. - * @throws UnknownCurrencyException if no such currency exists. - */ - public static Set getCurrencies(Locale locale, String... providers) { - return Optional.ofNullable(monetaryCurrenciesSingletonSpi()).orElseThrow( - () -> new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.")) - .getCurrencies(locale, providers); - } - - /** - * Allows to check if a {@link CurrencyUnit} instance is defined, i.e. - * accessible from {@link Monetary#getCurrency(String, String...)}. - * - * @param code the currency code, not {@code null}. - * @param providers the (optional) specification of providers to consider. - * @return {@code true} if {@link Monetary#getCurrency(String, java.lang.String...)} - * would return a result for the given code. - */ - public static boolean isCurrencyAvailable(String code, String... providers) { - return monetaryCurrenciesSingletonSpi().isCurrencyAvailable(code, providers); - } - - /** - * Allows to check if a {@link javax.money.CurrencyUnit} instance is - * defined, i.e. accessible from {@link #getCurrency(String, String...)}. - * - * @param locale the target {@link Locale}, not {@code null}. - * @param providers the (optional) specification of providers to consider. - * @return {@code true} if {@link #getCurrencies(Locale, String...)} would return a - * result containing a currency with the given code. - */ - public static boolean isCurrencyAvailable(Locale locale, String... providers) { - return monetaryCurrenciesSingletonSpi().isCurrencyAvailable(locale, providers); - } - - /** - * Access all currencies known. - * - * @param providers the (optional) specification of providers to consider. - * @return the list of known currencies, never null. - */ - public static Collection getCurrencies(String... providers) { - return monetaryCurrenciesSingletonSpi() - .getCurrencies(providers); - } - - /** - * Query all currencies matching the given query. - * - * @param query The {@link javax.money.CurrencyQuery}, not null. - * @return the list of known currencies, never null. - */ - public static CurrencyUnit getCurrency(CurrencyQuery query) { - return monetaryCurrenciesSingletonSpi() - .getCurrency(query); - } - - - /** - * Query all currencies matching the given query. - * - * @param query The {@link javax.money.CurrencyQuery}, not null. - * @return the list of known currencies, never null. - */ - public static Collection getCurrencies(CurrencyQuery query) { - return Optional.ofNullable(monetaryCurrenciesSingletonSpi()).orElseThrow( - () -> new MonetaryException("No MonetaryCurrenciesSingletonSpi loaded, check your system setup.")) - .getCurrencies(query); - } - - /** - * Query all currencies matching the given query. - * - * @return the list of known currencies, never null. - */ - public static Set getCurrencyProviderNames() { - return monetaryCurrenciesSingletonSpi() - .getProviderNames(); - } - - /** - * Query the list and ordering of provider names modelling the default provider chain to be used, if no provider - * chain was explicitly set.. - * - * @return the ordered list provider names, modelling the default provider chain used, never null. - */ - public static List getDefaultCurrencyProviderChain() { - return monetaryCurrenciesSingletonSpi() - .getDefaultProviderChain(); - } -} diff --git a/src/main/java/javax/money/MonetaryAmount.java b/src/main/java/javax/money/MonetaryAmount.java deleted file mode 100644 index 90e3d07da..000000000 --- a/src/main/java/javax/money/MonetaryAmount.java +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -/** - * Interface defining a monetary amount. The effective format representation of an amount may vary - * depending on the implementation used. JSR 354 explicitly supports different types of monetary - * amounts to be implemented and used. Reason behind is that the requirements to an implementation - * heavily vary for different usage scenarios. E.g. product calculations may require high precision - * and scale, whereas low latency order and trading systems require high calculation performance for - * algorithmic operations. - *

- * Each instance of an amount provides additional meta-data in form of a {@link MonetaryContext}. - * This context contains detailed information on the numeric capabilities, e.g. the supported - * precision and maximal scale, as well as the common implementation flavor. - * - * Also a {@link MonetaryAmount} provides a {@link NumberValue}, which allows easily to extract the - * numeric value, of the amount. And finally {@link #getFactory()} provides a - * {@link MonetaryAmountFactory}, which allows to of instances of {@link MonetaryAmount} based - * on the same numeric implementation. - *

- * This JSR additionally recommends to consider the following aspects: - *

    - *
  • Arithmetic operations should throw an {@link ArithmeticException}, if performing arithmetic - * operations between amounts exceeds the capabilities of the numeric representation type used. Any - * implicit truncating, that would lead to complete invalid and useless results, should be avoided. - * This recommendation does not affect format rounding, as required by the format numeric - * representation of a monetary amount. - *
  • Monetary amounts should allow numbers as argument for arithmetic operations like division and - * multiplication. Adding or subtracting of amounts must only be possible by passing instances of - * {@link MonetaryAmount}.
  • - *
  • Nevertheless numeric truncation is also explicitly supported when calling - * {@link NumberValue#numberValue(Class)}, whereas the exact counterpart, - * {@link NumberValue#numberValueExact(Class)}, works similar to - * {@link java.math.BigDecimal#longValueExact()}. - *
  • Since implementations are recommended to be immutable, an operation should never change any - * format state of an instance. Given an instance, all operations are required to be fully - * reproducible.
  • - *
  • Finally the result of calling {@link #with(MonetaryOperator)} must be of the same type as - * type on which {@code with} was called. The {@code with} method also defines additional - * interoperability requirements that are important to enable this invariant.
  • - *
  • To enable further interoperability a static method {@code from(MonetaryAmount)} is - * recommended to be implemented on each implementation class, that allows conversion of a - * {@code MonetaryAmount} to a concrete instance. E.g.a class {@code MyMoney extends MonetaryAmount} - * would contain the following method: - * - *
    - *
    
    - * public final class MyMoney implements MonetaryAmount{
    - *   ...
    - *   public static MyMoney from(MonetaryAmount amount)(...)
    - * }
    - * 
    - *
  • - *
- *

Implementation specification

- * Implementations of this interface must be - *
    - *
  • thread-safe
  • - *
- * Implementations of this interface should be - *
    - *
  • final
  • - *
  • serializable, hereby writing the numeric value, the {@link MonetaryContext} and a serialized - * {@link CurrencyUnit}.
  • - *
- * Implementations of this interface must be - *
    - *
  • thread-safe
  • - *
  • immutable
  • - *
  • comparable
  • - *
  • must implement {@code equals/hashCode}, hereby considering - *
      - *
    • Implementation type - *
    • CurrencyUnit - *
    • Numeric value. - *
    - * This also means that two different implementations types with the same currency and numeric value - * are NOT equal.
  • - *
- *

- * - * @author Anatole Tresch - * @author Werner Keil - * @version 1.1 - * @see #with(MonetaryOperator) - */ -public interface MonetaryAmount extends CurrencySupplier, NumberSupplier, Comparable{ - - /** - * Returns the {@link MonetaryContext} of this {@code MonetaryAmount}. The - * {@link MonetaryContext} provides additional information about the numeric representation and - * the numeric capabilities. This information can be used by code to determine situations where - * {@code MonetaryAmount} instances must be converted to avoid implicit truncation, which can - * lead to invalid results. - * - * @return the {@link MonetaryContext} of this {@code MonetaryAmount}, never {@code null} . - */ - MonetaryContext getContext(); - - /** - * Queries this monetary amount for a value. - *

- * This queries this amount using the specified query strategy object. - *

- * Implementations must ensure that no observable state is altered when this read-only method is - * invoked. - * - * @param the type of the result - * @param query the query to invoke, not null - * @return the query result, null may be returned (defined by the query) - */ - default R query(MonetaryQuery query){ - return query.queryFrom(this); - } - - /** - * Returns an operated object of the same type as this object with the operation made. - * Hereby returning an instance of the same type is very important to prevent - * uncontrolled mixup of implementations. Switching between implementations is still easily - * possible, e.g. by using according {@link MonetaryAmountFactory} instances:

- *

-     * // converting from Money to MyMoney
-     * Money m = ...;
-     * MonetartyAmountFactory<MyMoney> f = Monetary.queryAmountFactory(MyMoney.class);
-     * MyMoney myMoney = f.setAmount(m).of();
-     * 
- *

- * This converts this monetary amount according to the rules of the specified operator. A - * typical operator will change the amount and leave the currency unchanged. A more complex - * operator might also change the currency. - *

- * Some example code indicating how and why this method is used: - *

- *

-     * MonetaryAmount money = money.with(amountMultipliedBy(2));
-     * money = money.with(amountRoundedToNearestWholeUnit());
-     * 
- *
- *

- * Hereby also the method signature on the implementation type must return the concrete type, to - * enable a fluent API, e.g. - * - *

- *

-     * public final class MyMoney implements MonetaryAmount{
-     *   ...
-     *   public MyMoney with(MonetaryOperator operator){
-     *     ...
-     *   }
-     *
-     *   ...
-     * }
-     * 
- *
- * - * @param operator the operator to use, not null - * @return an object of the same type with the specified conversion made, not null - */ - default MonetaryAmount with(MonetaryOperator operator){ - return operator.apply(this); - } - - /** - * Creates a new {@code MonetaryAmountFactory}, returning the same implementation type Hereby - * this given amount is used as a template, so reusing the {@link CurrencyUnit}, its numeric - * value, the algorithmic implementation as well as the current {@link MonetaryContext}. - *

- * This method is used for creating a new amount result after having done calculations that are - * not directly mappable to the default monetary arithmetics, e.g. currency conversion. - * - * @return the new {@code MonetaryAmountFactory} with the given {@link MonetaryAmount} as its - * default values. - */ - MonetaryAmountFactory getFactory(); - - /** - * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing - * zeroes and different numeric capabilities. - * - * @param amount the {@code MonetaryAmount} to be compared with this instance. - * @return {@code true} if {@code amount > this}. - * @throws MonetaryException if the amount's currency is not equal to the currency of this instance. - */ - boolean isGreaterThan(MonetaryAmount amount); - - /** - * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing - * zeroes and different numeric capabilities. - * - * @param amount the {@link MonetaryAmount} to be compared with this instance. - * @return {@code true} if {@code amount >= this}. - * @throws MonetaryException if the amount's currency is not equal to the currency of this instance. - */ - boolean isGreaterThanOrEqualTo(MonetaryAmount amount); - - /** - * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing - * zeroes and different numeric capabilities. - * - * @param amount the {@link MonetaryAmount} to be compared with this instance. - * @return {@code true} if {@code amount < this}. - * @throws MonetaryException if the amount's currency is not equal to the currency of this instance. - */ - boolean isLessThan(MonetaryAmount amount); - - /** - * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing - * zeroes and different numeric capabilities. - * - * @param amt the {@link MonetaryAmount} to be compared with this instance. - * @return {@code true} if {@code amount <= this}. - * @throws MonetaryException if the amount's currency is not equal to the currency of this instance. - */ - boolean isLessThanOrEqualTo(MonetaryAmount amt); - - /** - * Compares two instances of {@link MonetaryAmount}, hereby ignoring non significant trailing - * zeroes and different numeric capabilities. - * - * @param amount the {@link MonetaryAmount} to be compared with this instance. - * @return {@code true} if {@code amount == this}. - * @throws MonetaryException if the amount's currency is not equal to the currency of this instance. - */ - boolean isEqualTo(MonetaryAmount amount); - - /** - * Checks if a {@code MonetaryAmount} is negative. - * - * @return {@code true} if {@link #signum()} < 0. - */ - default boolean isNegative(){ - return signum() < 0; - } - - /** - * Checks if a {@code MonetaryAmount} is negative or zero. - * - * @return {@code true} if {@link #signum()} <= 0. - */ - default boolean isNegativeOrZero(){ - return signum() <= 0; - } - - /** - * Checks if a {@code MonetaryAmount} is positive. - * - * @return {@code true} if {@link #signum()} > 0. - */ - default boolean isPositive(){ - return signum() > 0; - } - - /** - * Checks if a {@code MonetaryAmount} is positive or zero. - * - * @return {@code true} if {@link #signum()} >= 0. - */ - default boolean isPositiveOrZero(){ - return signum() >= 0; - } - - /** - * Checks if an {@code MonetaryAmount} is zero. - * - * @return {@code true} if {@link #signum()} == 0. - */ - default boolean isZero(){ - return signum() == 0; - } - - /** - * Returns the signum function of this {@code MonetaryAmount}. - * - * @return -1, 0, or 1 as the value of this {@code MonetaryAmount} is negative, zero, or - * positive. - */ - int signum(); - - /** - * Returns a {@code MonetaryAmount} whose value is this + augend, and whose scale is max(this.getContext().getMaxScale(), - * augend.getContext().getMaxScale()). - * - * @param augend value to be added to this {@code MonetaryAmount}. - * @return {@code this + augend} - * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. - * the {@link MonetaryContext} cannot be adapted as required. - */ - MonetaryAmount add(MonetaryAmount augend); - - /** - * Returns a {@code MonetaryAmount} whose value is this - - * amount, and whose scale is max(this.getContext().getMaxScale(), - * subtrahend.getContext().getMaxScale(). - * - * @param subtrahend value to be subtracted from this {@code MonetaryAmount}. - * @return {@code this - subtrahend} - * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. - * the {@link MonetaryContext} cannot be adapted as required. - */ - MonetaryAmount subtract(MonetaryAmount subtrahend); - - /** - * Returns a {@code MonetaryAmount} whose value is (this × - * multiplicand), and whose scale is this.getContext().getMaxScale() + - * multiplicand.getContext().getMaxScale(). - * - * @param multiplicand value to be multiplied by this {@code MonetaryAmount}. - * @return {@code this * multiplicand} - * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. - * the {@link MonetaryContext} cannot be adapted as required. - */ - MonetaryAmount multiply(long multiplicand); - - /** - * Returns a {@code MonetaryAmount} whose value is (this × - * multiplicand), and whose scale is this.getContext().getMaxScale() + - * multiplicand.getContext().getMaxScale(). - * By default the input value's scale will be rounded to - * accommodate the format capabilities, and no {@link java.lang.ArithmeticException} - * is thrown if the input number's scale exceeds the capabilities. - * - * @param multiplicand value to be multiplied by this {@code MonetaryAmount}. If the multiplicand's scale exceeds - * the - * capabilities of the implementation, it may be rounded implicitly. - * @return {@code this * multiplicand} - * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. - * the {@link MonetaryContext} cannot be adapted as required. - */ - MonetaryAmount multiply(double multiplicand); - - - /** - * Returns a {@code MonetaryAmount} whose value is (this × - * multiplicand), and whose scale is this.getContext().getMaxScale() + - * multiplicand.getContext().getMaxScale(). - * - * @param multiplicand value to be multiplied by this {@code MonetaryAmount}. If the multiplicand's scale exceeds - * the - * capabilities of the implementation, it may be rounded implicitly. - * @return {@code this * multiplicand} - * @throws ArithmeticException if the result exceeds the numeric capabilities of this implementation class, i.e. - * the {@link MonetaryContext} cannot be adapted as required. - */ - MonetaryAmount multiply(Number multiplicand); - - /** - * Returns a {@code MonetaryAmount} whose value is this / - * divisor, and whose preferred scale is this.getContext().getMaxScale() - - * divisor.getContext().getMaxScale(); if the exact quotient cannot be represented an {@code ArithmeticException} - * is thrown. - * - * @param divisor value by which this {@code MonetaryAmount} is to be divided. - * @return {@code this / divisor} - * @throws ArithmeticException if the exact quotient does not have a terminating decimal expansion, or if the - * result exceeds the numeric capabilities of this implementation class, i.e. the - * {@link MonetaryContext} cannot be adapted as required. - */ - MonetaryAmount divide(long divisor); - - /** - * Returns a {@code MonetaryAmount} whose value is this / - * divisor, and whose preferred scale is this.getContext().getMaxScale() - - * divisor.getContext().getMaxScale(); if the exact quotient cannot be represented an {@code ArithmeticException} - * is thrown. - * - * @param divisor value by which this {@code MonetaryAmount} is to be divided. - * @return {@code this / divisor} - * @throws ArithmeticException if the exact quotient does not have a terminating decimal expansion, or if the - * result exceeds the numeric capabilities of this implementation class, i.e. the - * {@link MonetaryContext} cannot be adapted as required. - */ - MonetaryAmount divide(double divisor); - - /** - * Returns a {@code MonetaryAmount} whose value is this / - * divisor, and whose preferred scale is this.getContext().getMaxScale() - - * divisor.getContext().getMaxScale(); if the exact quotient cannot be represented an {@code ArithmeticException} - * is thrown. - * - * @param divisor value by which this {@code MonetaryAmount} is to be divided. - * @return {@code this / divisor} - * @throws ArithmeticException if the exact quotient does not have a terminating decimal expansion, or if the - * result exceeds the numeric capabilities of this implementation class, i.e. the - * {@link MonetaryContext} cannot be adapted as required. - */ - MonetaryAmount divide(Number divisor); - - /** - * Returns a {@code MonetaryAmount} whose value is this % divisor. - * - *

- * The remainder is given by - * this.subtract(this.divideToIntegralValue(divisor).multiply(divisor) . Note that this - * is not the modulo operation (the result can be negative). - * - * @param divisor value by which this {@code MonetaryAmount} is to be divided. - * @return {@code this % divisor}. - * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this - * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as - * required. - */ - MonetaryAmount remainder(long divisor); - - /** - * Returns a {@code MonetaryAmount} whose value is this % divisor. - * - *

- * The remainder is given by - * this.subtract(this.divideToIntegralValue(divisor).multiply(divisor) . Note that this - * is not the modulo operation (the result can be negative). - * - * @param divisor value by which this {@code MonetaryAmount} is to be divided. - * @return {@code this % divisor}. - * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this - * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as - * required. - */ - MonetaryAmount remainder(double divisor); - - /** - * Returns a {@code MonetaryAmount} whose value is this % divisor. - * - *

- * The remainder is given by - * this.subtract(this.divideToIntegralValue(divisor).multiply(divisor) . Note that this - * is not the modulo operation (the result can be negative). - * - * @param divisor value by which this {@code MonetaryAmount} is to be divided. - * @return {@code this % divisor}. - * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this - * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as - * required. - */ - MonetaryAmount remainder(Number divisor); - - /** - * Returns a two-element {@code MonetaryAmount} array containing the result of - * {@code divideToIntegralValue} followed by the result of {@code remainder} on the two - * operands. - * - *

- * Note that if both the integer quotient and remainder are needed, this method is faster than - * using the {@code divideToIntegralValue} and {@code remainder} methods separately because the - * division need only be carried out once. - * - * @param divisor value by which this {@code MonetaryAmount} is to be divided, and the remainder - * computed. - * @return a two element {@code MonetaryAmount} array: the quotient (the result of - * {@code divideToIntegralValue}) is the initial element and the remainder is the final - * element. - * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this - * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as - * required. - * @see #divideToIntegralValue(long) - * @see #remainder(long) - */ - MonetaryAmount[] divideAndRemainder(long divisor); - - /** - * Returns a two-element {@code MonetaryAmount} array containing the result of - * {@code divideToIntegralValue} followed by the result of {@code remainder} on the two - * operands. - * - *

- * Note that if both the integer quotient and remainder are needed, this method is faster than - * using the {@code divideToIntegralValue} and {@code remainder} methods separately because the - * division need only be carried out once. - * - * @param divisor value by which this {@code MonetaryAmount} is to be divided, and the remainder - * computed. - * @return a two element {@code MonetaryAmount} array: the quotient (the result of - * {@code divideToIntegralValue}) is the initial element and the remainder is the final - * element. - * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this - * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as - * required. - * @see #divideToIntegralValue(double) - * @see #remainder(double) - */ - MonetaryAmount[] divideAndRemainder(double divisor); - - /** - * Returns a two-element {@code MonetaryAmount} array containing the result of - * {@code divideToIntegralValue} followed by the result of {@code remainder} on the two - * operands. - * - *

- * Note that if both the integer quotient and remainder are needed, this method is faster than - * using the {@code divideToIntegralValue} and {@code remainder} methods separately because the - * division need only be carried out once. - * - * @param divisor value by which this {@code MonetaryAmount} is to be divided, and the remainder - * computed. - * @return a two element {@code MonetaryAmount} array: the quotient (the result of - * {@code divideToIntegralValue}) is the initial element and the remainder is the final - * element. - * @throws ArithmeticException if {@code divisor==0}, or if the result exceeds the numeric capabilities of this - * implementation class, i.e. the {@link MonetaryContext} cannot be adapted as - * required. - * @see #divideToIntegralValue(Number) - * @see #remainder(Number) - */ - MonetaryAmount[] divideAndRemainder(Number divisor); - - /** - * Returns a {@code MonetaryAmount} whose value is the integer part of the quotient - * this / divisor rounded down. The preferred scale of the result is - * this.getContext().getMaxScale() - - * divisor.getContext().getMaxScale(). - * - * @param divisor value by which this {@code BigDecimal} is to be divided. - * @return The integer part of {@code this / divisor}. - * @throws ArithmeticException if {@code divisor==0} - * @see java.math.BigDecimal#divideToIntegralValue(java.math.BigDecimal) - */ - MonetaryAmount divideToIntegralValue(long divisor); - - /** - * Returns a {@code MonetaryAmount} whose value is the integer part of the quotient - * this / divisor rounded down. The preferred scale of the result is - * this.getContext().getMaxScale() - divisor.getContext().getMaxScale(). - * - * @param divisor value by which this {@code BigDecimal} is to be divided. - * @return The integer part of {@code this / divisor}. - * @throws ArithmeticException if {@code divisor==0} - * @see java.math.BigDecimal#divideToIntegralValue(java.math.BigDecimal) - */ - MonetaryAmount divideToIntegralValue(double divisor); - - /** - * Returns a {@code MonetaryAmount} whose value is the integer part of the quotient - * this / divisor rounded down. The preferred scale of the result is - * this.getContext().getMaxScale() - - * divisor.getContext().getMaxScale(). - * - * @param divisor value by which this {@code BigDecimal} is to be divided. - * @return The integer part of {@code this / divisor}. - * @throws ArithmeticException if {@code divisor==0} - * @see java.math.BigDecimal#divideToIntegralValue(java.math.BigDecimal) - */ - MonetaryAmount divideToIntegralValue(Number divisor); - - /** - * Returns a {@code MonetaryAmount} whose numerical value is equal to ( {@code this} * - * 10n). The scale of the result is this.getContext().getMaxScale() - n. - * - * @param power the power. - * @return the calculated amount value. - * @throws ArithmeticException if the scale would be outside the range of a 32-bit integer, or if the result - * exceeds the numeric capabilities of this implementation class, i.e. the - * {@link MonetaryContext} cannot be adapted as required. - */ - MonetaryAmount scaleByPowerOfTen(int power); - - /** - * Returns a {@code MonetaryAmount} whose value is the absolute value of this - * {@code MonetaryAmount}, and whose scale is {@code this.getContext().getMaxScale()}. - * - * @return abs(this - */ - MonetaryAmount abs(); - - /** - * Returns a {@code MonetaryAmount} whose value is -this, and whose scale is - * {@code this.getContext().getMaxScale()}, with rounding according to the context settings. - * - * @throws ArithmeticException if rounding fails. - * @return {@code -this}, rounded as necessary. - * @see java.math.BigDecimal#negate() - */ - MonetaryAmount negate(); - - /** - * Returns a {@code MonetaryAmount} whose value is +this. - * - *

This method, which simply returns this {@code MonetaryAmount} - * is included for symmetry with the unary minus method {@link #negate()}. - * - * @return {@code this}. - * @see #negate() - * @see java.math.BigDecimal#plus() - */ - MonetaryAmount plus(); - - /** - * Returns a {@code MonetaryAmount} which is numerically equal to this one but with any trailing - * zeros removed from the representation. For example, stripping the trailing zeros from the - * {@code MonetaryAmount} value {@code CHF 600.0}, which has [{@code BigInteger}, {@code scale}] - * components equals to [6000, 1], yields {@code 6E2} with [ {@code BigInteger}, {@code scale}] - * components equals to [6, -2] - * - * @return a numerically equal {@code MonetaryAmount} with any trailing zeros removed. - */ - MonetaryAmount stripTrailingZeros(); - -} diff --git a/src/main/java/javax/money/MonetaryAmountFactory.java b/src/main/java/javax/money/MonetaryAmountFactory.java deleted file mode 100644 index 882392094..000000000 --- a/src/main/java/javax/money/MonetaryAmountFactory.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -/** - * Factory for {@link MonetaryAmount} instances for a given type. It can be accessed, by - *

    - *
  • calling {@link MonetaryAmount#getFactory()}, returning a {@link MonetaryAmountFactory} - * creating amounts of the same implementation type, which also provided the factory instance.
  • - *
  • calling {@link Monetary#getAmountFactory(Class)} accessing a - * {@link MonetaryAmountFactory} for a concrete type Class<T>.
  • - *
  • calling {@link Monetary#getDefaultAmountFactory()} accessing a default - * {@link MonetaryAmountFactory}. - *
- *

- * Implementations of this interface allow to get {@link MonetaryAmount} instances providing - * different data as required: - *

    - *
  • the {@link CurrencyUnit}, or the corresponding currency code (must be solvable by - * {@link Monetary}).
  • - *
  • the number part
  • - *
  • the {@link MonetaryContext}
  • - *
  • by passing any {@link MonetaryAmount} instance, it is possible to convert an arbitrary amount - * implementation to the implementation provided by this factory. If the current factory cannot - * support the precision/scale as required by the current {@link NumberValue} a - * {@link MonetaryException} must be thrown.
  • - *
- * If not defined a default {@link MonetaryContext} is used, which can also be configured by adding - * configuration to a file {@code /javamoney.properties} to the classpath. - *

- * Hereby the entries. e.g. for a class {@code MyMoney} should start with {@code a.b.MyMoney.ctx}. The entries valid - * must be documented - * on the according implementation class, where the following entries are defined for all implementation types - * (example below given for a class {@code a.b.MyMoney}: - *

    - *
  • {@code a.b.MyMoney.ctx.precision} to define the maximal supported precision.
  • - *
  • {@code a.b.MyMoney.ctx.maxScale} to define the maximal supported scale.
  • - *
  • {@code a.b.MyMoney.ctx.fixedScale} to define the scale to be fixed (constant).
  • - *
- * - *

Implementation specification

Instances of this interface are not required to be - * thread-safe! - * - * @author Anatole Tresch - * @author Werner Keil - * @version 1.0.0 - */ -public interface MonetaryAmountFactory { - - /** - * Access the {@link MonetaryAmount} implementation type. - * - * @return the {@link MonetaryAmount} implementation type, never {@code null}. - */ - Class getAmountType(); - - /** - * Sets the {@link CurrencyUnit} to be used. - * - * @param currencyCode the currencyCode of the currency to be used, not {@code null}. The currency code - * will be resolved using {@link Monetary#getCurrency(String, String...)}. - * @return This factory instance, for chaining. - * @throws UnknownCurrencyException if the {@code currencyCode} is not resolvable. - */ - default MonetaryAmountFactory setCurrency(String currencyCode) { - return setCurrency(Monetary.getCurrency(currencyCode)); - } - - /** - * Sets the {@link CurrencyUnit} to be used. - * - * @param currency the {@link CurrencyUnit} to be used, not {@code null} - * @return This factory instance, for chaining. - */ - MonetaryAmountFactory setCurrency(CurrencyUnit currency); - - /** - * Sets the number to be used. - * - * @param number the number to be used - * @return This factory instance, for chaining. - */ - MonetaryAmountFactory setNumber(double number); - - /** - * Sets the number to be used. - * - * @param number the number to be used - * @return This factory instance, for chaining. - */ - MonetaryAmountFactory setNumber(long number); - - /** - * Sets the number to be used. - * - * @param number the number to be used, not {@code null}. - * @return This factory instance, for chaining. - */ - MonetaryAmountFactory setNumber(Number number); - - /** - * Get the maximum possible number that this type can represent. If the numeric model has no limitations on the - * numeric range, null should be returned. If {@link MonetaryContext#getPrecision()} returns a value > 0 this - * method is required to provide a maximal amount. - * - * @return the maximum possible number, or null. - */ - NumberValue getMaxNumber(); - - /** - * Get the minimum possible number that this type can represent. If the numeric model has no limitations on the - * numeric range, null should be returned. If {@link MonetaryContext#getPrecision()} returns a value > 0 this - * method is required to provide a maximal amount. - * - * @return the minimum possible number, or null. - */ - NumberValue getMinNumber(); - - /** - * Sets the {@link MonetaryContext} to be used. - * - * @param monetaryContext the {@link MonetaryContext} to be used, not {@code null}. - * @return This factory instance, for chaining. - * @throws MonetaryException when the {@link MonetaryContext} given exceeds the capabilities supported by this - * factory type. - * @see #getMaximalMonetaryContext() - */ - MonetaryAmountFactory setContext(MonetaryContext monetaryContext); - - /** - * Uses an arbitrary {@link MonetaryAmount} to initialize this factory. Properties reused are: - *
    - *
  • CurrencyUnit,
  • - *
  • Number value,
  • - *
  • MonetaryContext.
  • - *
- * - * @param amount the amount to be used, not {@code null}. - * @return this factory instance, for chaining. - * @throws MonetaryException when the {@link MonetaryContext} implied by {@code amount.getContext()} - * exceeds the capabilities supported by this factory type. - */ - default MonetaryAmountFactory setAmount(MonetaryAmount amount) { - setCurrency(amount.getCurrency()); - setNumber(amount.getNumber()); - setContext(amount.getContext()); - return this; - } - - /** - * Creates a new instance of {@link MonetaryAmount}, using the current data set on this factory. - * - * @return the corresponding {@link MonetaryAmount}. - * @see #getAmountType() - */ - T create(); - - /** - * Returns the default {@link MonetaryContext} used, when no {@link MonetaryContext} is - * provided. - *

- * The default context is not allowed to exceed the capabilities of the maximal - * {@link MonetaryContext} supported. - * - * @return the default {@link MonetaryContext}, never {@code null}. - * @see #getMaximalMonetaryContext() - */ - MonetaryContext getDefaultMonetaryContext(); - - /** - * Returns the maximal {@link MonetaryContext} supported, for requests that exceed these maximal - * capabilities, an {@link ArithmeticException} must be thrown. - * - * @return the maximal {@link MonetaryContext} supported, never {@code null} - */ - default MonetaryContext getMaximalMonetaryContext() { - return getDefaultMonetaryContext(); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/MonetaryAmountFactoryQuery.java b/src/main/java/javax/money/MonetaryAmountFactoryQuery.java deleted file mode 100644 index 9925d4042..000000000 --- a/src/main/java/javax/money/MonetaryAmountFactoryQuery.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.io.Serializable; - -/** - * Query to lookup instances of {@link MonetaryAmountFactory}, which are determined by the (minimal) - * capabilities required by the give use case. By default amount factories can be queried by - *

    - *
  • The maximal scale needed (THE ADDITIONAL fixed scale allows to define the minimal an maximal scale to - * be the same).
  • - *
  • The maximal numeric precision required.
  • - *
  • the target {@link javax.money.MonetaryAmount} implementation type.
  • - *
  • any other attributes, currently supported by the current factory and query implementation registered.
  • - *
- *

This class is thread-safe, final and serializable.

- * - * @see Monetary#getAmountFactory(MonetaryAmountFactoryQuery) - * @see MonetaryAmountFactory - */ -public final class MonetaryAmountFactoryQuery extends AbstractQuery implements Serializable { - - private static final long serialVersionUID = -6961037049540444782L; - - /** - * Key name for the context. - */ - private static final String KEY_PRECISION = "precision"; - - /** - * Key name for the currency provider. - */ - private static final String KEY_FIXED_SCALE = "fixedScale"; - - /** - * Key name for the max scale. - */ - private static final String KEY_MAX_SCALE = "maxScale"; - - /** - * Constructor, used from the {@link MonetaryAmountFactoryQueryBuilder}. - * - * @param builder the corresponding builder, not null. - */ - MonetaryAmountFactoryQuery(MonetaryAmountFactoryQueryBuilder builder) { - super(builder); - } - - /** - * Get the maximal scale to be supported. - * - * @return the maximal scale, or null, if this attribute must not be considered. - */ - public Integer getMaxScale() { - return getInt(KEY_MAX_SCALE); - } - - /** - * Get the maximal precision to be supported. - * - * @return the maximal precision, or null, if this attribute must not be considered. - */ - public Integer getPrecision() { - return getInt(KEY_PRECISION); - } - - /** - * Get the fixed scale flag to be supported. A fixed scale hereby means that the scale is always equal to - * the max scale (it could never be less). - * - * @return the fixed scale flag, or null, if this attribute must not be considered. - */ - public Boolean isFixedScale() { - return getBoolean(KEY_FIXED_SCALE); - } - - /** - * Creates a new builder instances, initialized with the data from this one. - * - * @return a new {@link MonetaryAmountFactoryQueryBuilder} instance, never null. - */ - public MonetaryAmountFactoryQueryBuilder toBuilder() { - return MonetaryAmountFactoryQueryBuilder.of(this); - } - -} diff --git a/src/main/java/javax/money/MonetaryAmountFactoryQueryBuilder.java b/src/main/java/javax/money/MonetaryAmountFactoryQueryBuilder.java deleted file mode 100644 index 3f377cd5a..000000000 --- a/src/main/java/javax/money/MonetaryAmountFactoryQueryBuilder.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.Objects; - -/** - * Builder class for creating new instances of {@link MonetaryAmountFactoryQuery} that can be passed - * to access {@link MonetaryAmountFactory} instances using a possible complex query. - *

- * Note this class is NOT thread-safe. - * - * @see javax.money.Monetary#getAmountFactory(MonetaryAmountFactoryQuery) - * @see MonetaryAmountFactory - */ -public final class MonetaryAmountFactoryQueryBuilder - extends AbstractQueryBuilder{ - - /** - * Creates a new instance of {@link javax.money.CurrencyQueryBuilder}. - * - * @param monetaryAmountFactoryQuery {@link MonetaryAmountFactoryQuery} used for initializing this - */ - private MonetaryAmountFactoryQueryBuilder(MonetaryAmountFactoryQuery monetaryAmountFactoryQuery){ - Objects.requireNonNull(monetaryAmountFactoryQuery); - importContext(monetaryAmountFactoryQuery); - } - - /** - * Default constructor. - */ - private MonetaryAmountFactoryQueryBuilder(){ - } - - /** - * Sets the maximal scale to be supported. - * - * @param maxScale the max scale, >= 0. - * @return this Builder for chaining. - */ - public MonetaryAmountFactoryQueryBuilder setMaxScale(int maxScale){ - return set("maxScale", maxScale); - } - - /** - * Sets the required precision, the value 0 models unlimited precision. - * - * @param precision the precision, >= 0, 0 meaning unlimited. - * @return this Builder for chaining. - */ - public MonetaryAmountFactoryQueryBuilder setPrecision(int precision){ - return set("precision", precision); - } - - /** - * Sets the flag if the scale should fixed, meaning minimal scale and maximal scale are always equally sized. - * - * @param fixedScale the fixed scale flag. - * @return this Builder for chaining. - */ - public MonetaryAmountFactoryQueryBuilder setFixedScale(boolean fixedScale){ - return set("fixedScale", fixedScale); - } - - /** - * Creates a new instance of {@link MonetaryAmountFactoryQuery} based on the values of this - * Builder. Note that - * the Builder supports creation of several Builder instances from the a common Builder instance. But be aware - * that the keys and values contained are themselves not recursively cloned (deep-copy). - * - * @return a new {@link MonetaryAmountFactoryQuery} instance. - */ - public MonetaryAmountFactoryQuery build(){ - return new MonetaryAmountFactoryQuery(this); - } - - /** - * Creates a new instance of {@link javax.money.CurrencyQueryBuilder}. - * - * @return a new {@link javax.money.CurrencyQueryBuilder} instance, never null. - */ - public static MonetaryAmountFactoryQueryBuilder of(){ - return new MonetaryAmountFactoryQueryBuilder(); - } - - /** - * Creates a new instance of {@link javax.money.CurrencyQueryBuilder}. - * - * @param monetaryAmountFactoryQuery {@link MonetaryAmountFactoryQuery} used for initializing this - * builder. - * @return a new {@link MonetaryAmountFactoryQueryBuilder} instance, never null. - */ - - public static MonetaryAmountFactoryQueryBuilder of(MonetaryAmountFactoryQuery monetaryAmountFactoryQuery){ - return new MonetaryAmountFactoryQueryBuilder(monetaryAmountFactoryQuery); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/MonetaryContext.java b/src/main/java/javax/money/MonetaryContext.java deleted file mode 100644 index cadc6ed96..000000000 --- a/src/main/java/javax/money/MonetaryContext.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.io.Serializable; - -/** - * This class models the meta data (mostly the numeric capabilities) of a {@link MonetaryAmount} in a - * platform independent way. It provides information about - *

    - *
  • the maximal precision supported (0, for unlimited precision). - *
  • the minimum scale (>=0) - *
  • the maximal scale (>= -1, -1 for unlimited scale). - *
  • the numeric representation class. - *
  • any other attributes, identified by the attribute type, e.g. - * {@link java.math.RoundingMode}. - *
- *

- * This class is immutable, serializable and thread-safe. - * - * @author Anatole Tresch - * @author Werner Keil - * @version 1.5 - */ -public final class MonetaryContext extends AbstractContext implements Serializable { - - private static final long serialVersionUID = 500722564420978659L; - - /** - * Constant that defines under which key the amount type is stored in the context map. - */ - static final String AMOUNT_TYPE = "amountType"; - - /** - * Key name for the precision. - */ - private static final String PRECISION = "precision"; - - /** - * Key name for the fixed scale. - */ - private static final String FIXED_SCALE = "fixedScale"; - - /** - * Key name for the max scale. - */ - private static final String MAX_SCALE = "maxScale"; - - /** - * Constructor, used from the Builder. - * - * @param builder the corresponding builder, not null. - */ - MonetaryContext(MonetaryContextBuilder builder) { - super(builder); - } - - /** - * Returns the {@code precision} setting. This value is always non-negative. - * - * @return an {@code int} which is the value of the {@code precision} - * setting - */ - public int getPrecision() { - Integer val = getInt(PRECISION); - if (val == null) { - return 0; - } - return val; - } - - /** - * Allows to check if {@code scale == maxScale}. - * - * @return {@code true} if {@code scale == maxScale}. - */ - public boolean isFixedScale() { - Boolean val = getBoolean(FIXED_SCALE); - if (val == null) { - return false; - } - return val; - } - - /** - * Get the maximal scale supported, always {@code >= -1}. Fixed scaled - * numbers will have {@code scale==maxScale} for all values. {@code -1} - * declares the maximal scale to be unlimited. - * - * @return the maximal scale supported, always {@code >= -1} - */ - public int getMaxScale() { - Integer val = getInt(MAX_SCALE); - if (val == null) { - return -1; - } - return val; - } - - /** - * Get the MonetaryAmount implementation class. - * - * @return the implementation class of the containing amount instance, never null. - * @see MonetaryAmount#getContext() - */ - public Class getAmountType() { - Class clazz = get(AMOUNT_TYPE, Class.class); - return clazz.asSubclass(MonetaryAmount.class); - } - - /** - * This method allows to easily of a new MonetaryContext instance from a given {@link javax.money - * .MonetaryAmountFactoryQuery}. - * - * @param monetaryAmountFactoryQuery the monetary amount factory query, not null. - * @param amountClass the targeted implementation type. - * @return a new corresponding MonetaryContext instance. - */ - public static MonetaryContext from(MonetaryAmountFactoryQuery monetaryAmountFactoryQuery, - Class amountClass) { - return MonetaryContextBuilder.of(amountClass).importContext(monetaryAmountFactoryQuery).build(); - } - - /** - * Creates a new {@link }MonetaryContext). - * - * @param monetaryContext the base context, not null. - * @param amountClass the target amount class. - * @return a new corresponding MonetaryContext instance. - */ - public static MonetaryContext from(MonetaryContext monetaryContext, Class amountClass) { - return MonetaryContextBuilder.of(amountClass).importContext(monetaryContext).build(); - } - - /** - * Creates a new builder instances, initialized with the data from this one. - * - * @return a new {@link javax.money.MonetaryContextBuilder} instance, never null. - */ - public MonetaryContextBuilder toBuilder() { - return MonetaryContextBuilder.of(this); - } - -} diff --git a/src/main/java/javax/money/MonetaryContextBuilder.java b/src/main/java/javax/money/MonetaryContextBuilder.java deleted file mode 100644 index b30b7b939..000000000 --- a/src/main/java/javax/money/MonetaryContextBuilder.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - - -/** - * Builder class for creating new instances of {@link MonetaryContext} adding detailed information - * about a {@link MonetaryAmount} instance. - *

- * Note this class is NOT thread-safe. - * - * @see javax.money.MonetaryAmount#getContext() - */ -public final class MonetaryContextBuilder extends AbstractContextBuilder { - - private MonetaryContextBuilder(MonetaryContext monetaryContext) { - importContext(monetaryContext); - } - - /** - * Creates a new builder, hereby the target implementation type is required. This can be used to explicitly - * acquire a specific amount type and additionally configure the amount factory with the attributes in this - * query. - * - * @param amountType the target amount type, not null. - */ - private MonetaryContextBuilder(Class amountType) { - set(MonetaryContext.AMOUNT_TYPE, amountType); - } - - - /** - * Set the maximal scale to be supported. - * - * @param maxScale the max scale, >= 0. - * @return this builder for chaining. - */ - public MonetaryContextBuilder setMaxScale(int maxScale) { - return set("maxScale", maxScale); - } - - /** - * Set the required precision. - * - * @param precision the precision, >= 0, 0 meaning unlimited. - * @return this builder for chaining. - */ - public MonetaryContextBuilder setPrecision(int precision) { - return set("precision", precision); - } - - /** - * Set the flag if the scale should fixed. - * - * @param fixedScale the fixed scale flag. - * @return this builder for chaining. - */ - public MonetaryContextBuilder setFixedScale(boolean fixedScale) { - return set("fixedScale", fixedScale); - } - - /** - * Set the MonetaryAmount implementation class. - * - * @param amountType the target amount type, not null. - * @return the implementation class of the containing amount instance, never null. - * @see javax.money.MonetaryAmount#getContext() - */ - public MonetaryContextBuilder setAmountType(Class amountType) { - return set(MonetaryContext.AMOUNT_TYPE, amountType); - } - - /** - * Creates a new instance of {@link MonetaryAmountFactoryQuery}. - * - * @return a new {@link MonetaryAmountFactoryQuery} instance. - */ - public MonetaryContext build() { - return new MonetaryContext(this); - } - - /** - * Creates a new builder, hereby the target implementation type is required. This can be used to explicitly - * acquire a specific amount type and additionally configure the amount factory with the attributes in this - * query. - * - * @return a new {@link javax.money.MonetaryContextBuilder} instance, never null. - */ - public static MonetaryContextBuilder of() { - return of(MonetaryAmount.class); - } - - /** - * Creates a new builder, using an existing {@link javax.money.MonetaryContext} as a template. - * - * @return a new {@link javax.money.MonetaryContextBuilder} instance, never null. - */ - public static MonetaryContextBuilder of(MonetaryContext monetaryContext) { - return new MonetaryContextBuilder(monetaryContext); - } - - /** - * Creates a new builder, hereby the target implementation type is required. This can be used to explicitly - * acquire a specific amount type and additionally configure the amount factory with the attributes in this - * query. - * - * @param amountType the target amount type, not null. - * @return a new {@link javax.money.MonetaryContextBuilder} instance, never null. - */ - public static MonetaryContextBuilder of(Class amountType) { - return new MonetaryContextBuilder(amountType); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/MonetaryException.java b/src/main/java/javax/money/MonetaryException.java deleted file mode 100644 index ab8f51bc5..000000000 --- a/src/main/java/javax/money/MonetaryException.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -/** - * Exception thrown when an error occurs during monetary operations. - * - * @author Werner Keil - * @author Anatole Tresch - */ -public class MonetaryException extends RuntimeException { - - /** - * serialVersionUID. - */ - private static final long serialVersionUID = -9039026008242959369L; - - /** - * Creates an instance. - * - * @param message the message - */ - public MonetaryException(String message) { - super(message); - } - - /** - * Creates an instance with the specified detail message and cause. - * - * @param message - * the detail message (which is saved for later retrieval by the - * {@link Throwable#getMessage()} method). - * @param cause - * the cause (which is saved for later retrieval by the - * {@link Throwable#getCause()} method). (A null value - * is permitted, and indicates that the cause is nonexistent or - * unknown.) - */ - public MonetaryException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/javax/money/MonetaryOperator.java b/src/main/java/javax/money/MonetaryOperator.java deleted file mode 100644 index 20c72efe3..000000000 --- a/src/main/java/javax/money/MonetaryOperator.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -/** - * Represents an operation on a single {@link MonetaryAmount} that produces a - * result of type {@link MonetaryAmount}. - *

- * Examples might be an operator that rounds the amount to the nearest 1000, or - * one that performs currency conversion. - *

- * - *

- * There are two equivalent ways of using a {@code MonetaryOperator}. The first - * is to invoke the method on this interface. The second is to use - * {@link MonetaryAmount#with(MonetaryOperator)}: - *

- * - *

- * // these two lines are equivalent, but the second approach is recommended
- * monetary = thisOperator.apply(monetary);
- * monetary = monetary.with(thisOperator);
- * 
- * - * It is recommended to use the second approach, {@code with(MonetaryOperator)}, - * as it is a lot clearer to read in code. - * - *

Implementation specification

- *

- * The implementation must take the input object and apply it. The - * implementation defines the logic of the operator and is responsible for - * documenting that logic. It may use any method on {@code MonetaryAmount} to - * determine the result. - *

- * - *

- * The input object must not be altered. Instead, an altered copy of the - * original must be returned. This provides equivalent, safe behavior for - * immutable and mutable monetary amounts. - *

- * - *

- * This method may be called from multiple threads in parallel. It must be - * thread-safe when invoked. - *

- * - * @author Werner Keil - * @author Anatole Tresch - * - * @version 1.0 - */ -@FunctionalInterface -public interface MonetaryOperator{ - - /** - * Applies the operator on the given amount. - * @param amount the amount to be operated on. - * @return the applied amount. - */ - MonetaryAmount apply(MonetaryAmount amount); -} diff --git a/src/main/java/javax/money/MonetaryQuery.java b/src/main/java/javax/money/MonetaryQuery.java deleted file mode 100644 index 34ef6b0e9..000000000 --- a/src/main/java/javax/money/MonetaryQuery.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -/** - * Strategy for querying a monetary amount. - *

- * Queries are a key tool for extracting information from monetary amounts. They - * match the strategy design pattern, allowing different types of query to be - * easily captured. Examples might be a query that checks if the amount is - * positive, or one that extracts the currency as a symbol. - *

- * There are two equivalent ways of using a {@code MonetaryQuery}. The first is - * to invoke the method on this interface. The second is to use - * {@link MonetaryAmount#query(MonetaryQuery)}: - * - *


- * // these two lines are equivalent, but the second approach is recommended
- * monetary = thisQuery.queryFrom(monetary);
- * // Recommended approach
- * monetary = monetary.query(thisQuery);
- * 
- * - * It is recommended to use the second approach, {@code query(MonetaryQuery)}, - * as it is a lot clearer to read in code. - *

Implementation specification

- * This interface places no restrictions on the mutability of implementations, - * however immutability is strongly recommended. - * - * @param - * the return type. - * @author Anatole Tresch - * @author Stephen Colebourne - * @author Werner Keil - * @version 1.0 - */ -@FunctionalInterface -public interface MonetaryQuery{ - - /** - * Queries the specified monetary amount. - *

- * This queries the specified monetary amount to return an object using the - * logic encapsulated in the implementing class. Examples might be a query - * that checks if the amount is positive, or one that extracts the currency - * as a symbol. - *

- * There are two equivalent ways of using a {@code MonetaryQuery}. The first - * is to invoke the method on this interface. The second is to use - * {@link MonetaryAmount#query(MonetaryQuery)}: - * - *

-	 * // these two lines are equivalent, but the second approach is recommended
-	 * monetary = thisQuery.queryFrom(monetary);
-	 * monetary = monetary.query(thisQuery);
-	 * 
- * - * It is recommended to use the second approach, - * {@code query(MonetaryQuery)}, as it is a lot clearer to read in code. - * - *

Implementation specification

- * The implementation must take the input object and query it. The - * implementation defines the logic of the query and is responsible for - * documenting that logic. It may use any method on {@code MonetaryAmount} - * to determine the result. The input object must not be altered. - *

- * This method may be called from multiple threads in parallel. It must be - * thread-safe when invoked. - * - * @param amount - * the monetary amount to query, not null - * @return the queried value, may return null to indicate not found - * @throws MonetaryException - * if unable to query - * @throws ArithmeticException - * if numeric overflow occurs - */ - R queryFrom(MonetaryAmount amount); - -} \ No newline at end of file diff --git a/src/main/java/javax/money/MonetaryRounding.java b/src/main/java/javax/money/MonetaryRounding.java deleted file mode 100644 index 806359b4e..000000000 --- a/src/main/java/javax/money/MonetaryRounding.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -/** - * Interface representing a monetary rounding. Rounding must not necessarily represent roundings in a pure arithmetical sense. Basically a rounding - * can scale an amount arbitrarily. - *

Implementation specification

- * Implementations of this interface must be - *
    - *
  • final
  • - *
  • immutable
  • - *
  • thread-safe
  • - *
- * Implementations of this interface should be - *
    - *
  • serializable
  • - *
- */ -public interface MonetaryRounding extends MonetaryOperator{ - - /** - * Access the rounding's context, which gives more details of the rounding instances such as - *
    - *
  • The rounding's name (required)
  • - *
  • Its provider (required)
  • - *
  • Its base currency
  • - *
  • its scale and rounding mode
  • - *
  • any other attributes useful to describe the rounding
  • - *
- * @return the rounding's context, never null. - */ - RoundingContext getRoundingContext(); - -} diff --git a/src/main/java/javax/money/NumberSupplier.java b/src/main/java/javax/money/NumberSupplier.java deleted file mode 100644 index 12fdaa326..000000000 --- a/src/main/java/javax/money/NumberSupplier.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - - -/** - *

- * Represents a supplier of {@link NumberValue}-valued results. This is the - * {@link NumberValue}-producing specialization of {@code Supplier} (as in Java 8). - * - *

- * There is no requirement that a distinct result be returned each time the - * supplier is invoked. - * - *

- * This is a functional interface whose - * functional method is {@link #getNumber()}. - * This class does not extend {@link java.util.function.Supplier} since {@link javax.money.MonetaryAmount} implements - * both supplier interfaces, {@link javax.money.NumberSupplier} and {@link javax.money.CurrencySupplier}, - * which will lead - * to method name conflicts. - *

- * - * @author Werner Keil - * @author Anatole Tresch - * @version 1.0 - * @see java.util.function.Supplier - * @since 0.8 - */ -@FunctionalInterface -public interface NumberSupplier{ - - /** - * Gets the corresponding {@link javax.money.NumberValue}. - * - * @return the corresponding {@link javax.money.NumberValue}, not null. - */ - NumberValue getNumber(); -} diff --git a/src/main/java/javax/money/NumberValue.java b/src/main/java/javax/money/NumberValue.java deleted file mode 100644 index a7c0458ce..000000000 --- a/src/main/java/javax/money/NumberValue.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.math.BigDecimal; -import java.math.MathContext; - -/** - * Instances of this class allow to externalize the numeric value of a {@link MonetaryAmount}. The class extends - * {@link java.lang.Number} for maximal compatibility with the JDK but also adds additional functionality to - * overcome some of the pitfalls of the JDK's Number class. - *

Implementation specification

- *

Implementations of this interface must be :

- *
    - *
  • Comparable, hereby comparing the numeric value.
  • - *
  • immutable
  • - *
  • serializable
  • - *
  • thread-safe
  • - *
- * - * @author Anatole Tresch - */ -public abstract class NumberValue extends Number implements Comparable { - - /** - * serialVersionUID. - */ - private static final long serialVersionUID = -6410309081241720626L; - - /** - * Get the numeric implementation type, that is the base of this number. - * - * @return the numeric implementation type, not {@code null}. - */ - public abstract Class getNumberType(); - - /** - * Returns the precision of this {@code MonetaryAmount}. (The precision is the number of - * digits in the unscaled value.) - * - *

- * The precision of a zero value is 1. - * - * @return the precision of this {@code MonetaryAmount}. - */ - public abstract int getPrecision(); - - /** - * Returns the scale of this {@code MonetaryAmount}. If zero or positive, the scale is - * the number of digits to the right of the decimal point. If negative, the unscaled value of - * the number is multiplied by ten to the power of the negation of the scale. For example, a - * scale of {@code -3} means the unscaled value is multiplied by 1000. - * - * @return the scale of this {@code MonetaryAmount}. - */ - public abstract int getScale(); - - /** - * Access the numeric value as {@code int}. Hereby no truncation will be performed to fit the - * value into the target data type. - * - * @return the (possibly) truncated value of the {@link MonetaryAmount}. - * @throws ArithmeticException If the value must be truncated to fit the target datatype. - */ - public abstract int intValueExact(); - - /** - * Access the numeric value as {@code long}. Hereby no truncation will be performed to fit the - * value into the target data type. - * - * @return the (possibly) truncated value of the {@link MonetaryAmount}. - * @throws ArithmeticException If the value must be truncated to fit the target datatype. - */ - public abstract long longValueExact(); - - /** - * Access the numeric value as {@code double}. Hereby no truncation will be performed to fit the - * value into the target data type. - * - * @return the (possibly) truncated value of the {@link MonetaryAmount}. - * @throws ArithmeticException If the value must be truncated to fit the target datatype. - */ - public abstract double doubleValueExact(); - - /** - * Access the numeric value as {@code Number}. Hereby truncation may be performed as needed to - * fit the value into the target data type. - * - * @param numberType The concrete number class to be returned. Basically the following Number types, - * must be supported if available on the corresponding runtime platform: - *

    - *
  • {@code java.lang.Long}
  • - *
  • {@code java.lang.Double}
  • - *
  • {@code java.lang.Number}
  • - *
  • {@code java.math.BigInteger}, currently not available on all platforms.
  • - *
  • {@code java.math.BigDecimal}, currently not available on all platforms.
  • - *
- * @return the (possibly) truncated value of the {@link MonetaryAmount}. - */ - public abstract T numberValue(Class numberType); - - /** - * Access the current NumberValue rounded using the given {@link java.math.MathContext}. - * - * @param mathContext the {@link java.math.MathContext} to be applied. - * @return the new NumberValue, never null. - * @see java.math.BigDecimal#round(java.math.MathContext) - */ - public abstract NumberValue round(MathContext mathContext); - - /** - * Access the numeric value as {@code Number}. Hereby no truncation will be performed to fit the - * value into the target data type. - * - * @param numberType The concrete number class to be returned. Basically the following Number types, - * must be supported if available on the corresponding runtime platform: - *
    - *
  • {@code java.lang.Long}
  • - *
  • {@code java.lang.Double}
  • - *
  • {@code java.lang.Number}
  • - *
  • {@code java.math.BigInteger}, currently not available on all platforms.
  • - *
  • {@code java.math.BigDecimal}, currently not available on all platforms.
  • - *
- * @return the (possibly) truncated value of the {@link MonetaryAmount}. - * @throws ArithmeticException If the value must be truncated to fit the target datatype. - */ - public abstract T numberValueExact(Class numberType); - - /** - * This method allows to extract the numerator part of the current fraction, hereby given - *

-     * w = longValue()
-     * n = getFractionNominator()
-     * d = getFractionDenominator()
-     * 
- * - * the following must be always true: - * - *

-     * !(w<0 && n>0)  and
-     * !(w>0 && n<0)  and
-     * d>0            and
-     * |n| < d        // || = absolute value
-     * 
. - * - * @return the amount's fraction numerator.. - */ - public abstract long getAmountFractionNumerator(); - - /** - * This method allows to extract the denominator part of the current fraction, hereby given - *

-     * w = longValue()
-     * n = getFractionNominator()
-     * d = getFractionDenominator()
-     * 
- * - * the following must be always true: - * - *

-     * !(w<0 && n>0)  and
-     * !(w>0 && n<0)  and
-     * d>0            and
-     * |n| < d        // || = absolute value
-     * 
. - * - * @return the amount's fraction denominator. - */ - public abstract long getAmountFractionDenominator(); - - @Override - public int compareTo(NumberValue other) { - return numberValue(BigDecimal.class).compareTo(other.numberValue(BigDecimal.class)); - } - -} diff --git a/src/main/java/javax/money/RoundingContext.java b/src/main/java/javax/money/RoundingContext.java deleted file mode 100644 index 4b8398b1d..000000000 --- a/src/main/java/javax/money/RoundingContext.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.io.Serializable; - -/** - * This class models the spec/configuration for a rounding, modeled as {@link javax.money.MonetaryRounding} in a - * platform independent way. Each RoundingContext instance hereby has a roundingId, which links - * to the {@link javax.money.spi.RoundingProviderSpi} that must of the according rounding instance. The - * default roundingId is default. - *

- * A RoundingContext can take up arbitrary attributes that must be documented by the - * {@link javax.money.spi.RoundingProviderSpi} implementations. - *

- * Examples for such additional attributes are - * {@link java.math.RoundingMode}, {@link java.math.MathContext}, additional regional information, - * e.g. if a given rounding is targeting cash rounding. - *

- * This class is immutable, serializable, thread-safe. - * - * @author Anatole Tresch - */ -public final class RoundingContext extends AbstractContext implements Serializable, CurrencySupplier { - - private static final long serialVersionUID = -1879443887564347935L; - - /** - * Attribute key used for the rounding name. - */ - static final String KEY_ROUNDING_NAME = "roundingName"; - - /** - * Constructor, used from the {@link javax.money.RoundingContextBuilder}. - * - * @param builder the corresponding builder, not null. - */ - RoundingContext(RoundingContextBuilder builder) { - super(builder); - } - - /** - * Get the (custom) rounding id. - * - * @return the rounding id, or null. - */ - public String getRoundingName() { - return getText(KEY_ROUNDING_NAME); - } - - /** - * Get the basic {@link javax.money.CurrencyUnit}, which is based for this rounding type. - * - * @return the target CurrencyUnit, or null. - */ - public CurrencyUnit getCurrency() { - return get(CurrencyUnit.class); - } - - /** - * Allows to convert a instance into the corresponding {@link javax.money.CurrencyContextBuilder}, which allows - * to change the values and of another {@link javax.money.CurrencyContext} instance. - * - * @return a new Builder instance, preinitialized with the values from this instance. - */ - public RoundingContextBuilder toBuilder() { - return RoundingContextBuilder.of(this); - } - -} diff --git a/src/main/java/javax/money/RoundingContextBuilder.java b/src/main/java/javax/money/RoundingContextBuilder.java deleted file mode 100644 index ecc74f377..000000000 --- a/src/main/java/javax/money/RoundingContextBuilder.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.Objects; - -/** - * Builder class for creating new instances of {@link RoundingContext} adding detailed information - * about a {@link MonetaryRounding} instance. - *

- * Note this class is NOT thread-safe. - * - * @see javax.money.MonetaryRounding#getRoundingContext() () - */ -public final class RoundingContextBuilder extends AbstractContextBuilder { - - /** - * Creates a new builder. - * - * @param provider the provider name, creating the corresponding {@link MonetaryRounding} - * containing, not null. - * the final {@link RoundingContext} created by this builder, not null. - * @param roundingId The name of the rounding, not null. - */ - private RoundingContextBuilder(String provider, String roundingId) { - Objects.requireNonNull(provider); - set(RoundingContext.KEY_PROVIDER, provider); - Objects.requireNonNull(roundingId); - set(RoundingContext.KEY_ROUNDING_NAME, roundingId); - } - - /** - * Creates a new RoundingContextBuilder. - * - * @param roundingContext the rounding context, used as a template, not null. - */ - private RoundingContextBuilder(RoundingContext roundingContext) { - importContext(roundingContext); - } - - /** - * Get the basic {@link CurrencyUnit}, which is based for this rounding type. - * @param currencyUnit the target currency unit not null. - * @return the target CurrencyUnit, or null. - */ - public RoundingContextBuilder setCurrency(CurrencyUnit currencyUnit) { - Objects.requireNonNull(currencyUnit); - return set(CurrencyUnit.class, currencyUnit); - } - - /** - * Creates a new instance of {@link javax.money.RoundingContext}. - * - * @return a new {@link javax.money.RoundingContext} instance. - */ - @Override - public RoundingContext build() { - return new RoundingContext(this); - } - - /** - * Creates a new RoundingContextBuilder. - * - * @param provider the provider name, creating the corresponding {@link MonetaryRounding} - * containing, not null. - * the final {@link RoundingContext} created by this builder, not null. - * @param roundingId The name of the rounding, not null. - * @return a new {@link javax.money.MonetaryContextBuilder} instance, never null. - */ - public static RoundingContextBuilder of(String provider, String roundingId) { - return new RoundingContextBuilder(provider, roundingId); - } - - /** - * Creates a new RoundingContextBuilder. - * - * @param roundingContext the rounding context, used as a template, not null. - * @return a new {@link javax.money.MonetaryContextBuilder} instance, never null. - */ - public static RoundingContextBuilder of(RoundingContext roundingContext) { - return new RoundingContextBuilder(roundingContext); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/RoundingQuery.java b/src/main/java/javax/money/RoundingQuery.java deleted file mode 100644 index 9b554522a..000000000 --- a/src/main/java/javax/money/RoundingQuery.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -/** - * Query for accessing instances of {@link javax.money.MonetaryRounding}. In general it is determined by the - * implementation, what roundings are provided. Nevertheless the following queries must be supported: - *

    - *
  • Accessing roundings using rounding names and/or regular expressions.
  • - *
  • Accessing mathematical rounding by setting a scale and (optionally) a {@link java.math.MathContext} as - * additional generic attribute.
  • - *
  • Accessing default roundings for a {@link javax.money.CurrencyUnit}. This method should return the most - * appropriate rounding for a currency. If no - * currency specific rounding is available, it should return a rounding with {@code scale==currency - * .getDefaultFractionUnits(), java.math.RoundingMode = RoundingMode.HALF_EVEN}.
  • - *
- * All other roundings including cash rounding and historical roundings are optional. - *

- * This class is immutable, thread-safe and serializable. - */ -public final class RoundingQuery extends AbstractQuery implements CurrencySupplier { - - private static final long serialVersionUID = -9088736532066489061L; - - /** - * Attribute key used for the rounding name attribute. - */ - static final String KEY_QUERY_ROUNDING_NAME = "Query.roundingName"; - - /** - * Attribute key used for the scale attribute. - */ - static final String KEY_QUERY_SCALE = "Query.scale"; - - /** - * Constructor, used from the {@link javax.money.RoundingQueryBuilder}. - * - * @param builder the corresponding builder, not null. - */ - RoundingQuery(RoundingQueryBuilder builder) { - super(builder); - } - - /** - * Gets the target rounding name. This method allows to - * access the {@link javax.money.MonetaryRounding} instances by passing a name, which most of the time - * identifies a certain rounding instance. Each entry is first matched as name on equality. If no instance - * with such a name exists, the value passed is interpreted as a regular - * expression to lookup roundings. - * - * @return the rounding id or null. - */ - public String getRoundingName() { - return getText(KEY_QUERY_ROUNDING_NAME); - } - - /** - * Gets the target scale. This allows to define the scale required. If not specified as additional - * attribute, by default, RoundingMode.HALF_EVEN is used hereby. - * - * @return the target scale or null. - */ - public Integer getScale() { - return getInt(KEY_QUERY_SCALE); - } - - /** - * Sets the target CurrencyUnit. Typically this determines all other properties, - * such as scale and the concrete rounding algorithm. With - * rounding names, depending on the implementation, additional sub-selections are possible. Similarly - * additional attributes can be used to select special rounding instances, e.g. for cash rounding. - * - * @return the CurrencyUnit, or null. - */ - @Override - public CurrencyUnit getCurrency() { - return get(CurrencyUnit.class); - } - - /** - * Creates a new builder instances, initialized with the data from this one. - * - * @return a new {@link javax.money.RoundingQueryBuilder} instance, never null. - */ - public RoundingQueryBuilder toBuilder() { - return RoundingQueryBuilder.of(this); - } - -} diff --git a/src/main/java/javax/money/RoundingQueryBuilder.java b/src/main/java/javax/money/RoundingQueryBuilder.java deleted file mode 100644 index b8f5c52d3..000000000 --- a/src/main/java/javax/money/RoundingQueryBuilder.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.Objects; - - -/** - * Builder used to construct new instances of {@link }RoundingQuery}. - *

- * Note this class is NOT thread-safe. - */ -public final class RoundingQueryBuilder extends AbstractQueryBuilder { - - /** - * Default constructor. - */ - private RoundingQueryBuilder() { - super(); - } - - /** - * Creates a new RoundingQueryBuilder. - * - * @param roundingQuery the rounding query, used as a template, not null. - */ - private RoundingQueryBuilder(RoundingQuery roundingQuery) { - importContext(roundingQuery); - } - - /** - * Sets the rounding names of the {@link MonetaryRounding} instances. This method allows to - * access the {@link MonetaryRounding} instances by passing a name, which most of the time - * identifies a certain rounding instance. Each entry is first matched as name on equality. If no instance - * with such a name exists, the value passed is interpreted as a regular - * expression to lookup roundings. - * - * @param roundingName the (custom) rounding name expression, not {@code null}. - * @return this instance for chaining - */ - public RoundingQueryBuilder setRoundingName(String roundingName) { - Objects.requireNonNull(roundingName); - set(RoundingQuery.KEY_QUERY_ROUNDING_NAME, roundingName); - return this; - } - - - /** - * Sets the target scale. This allows to define the scale required. If not specified as additional - * attribute, by default, RoundingMode.HALF_EVEN is used hereby. - * - * @param scale the target scale, >0. - * @return this instance for chaining - */ - public RoundingQueryBuilder setScale(int scale) { - set(RoundingQuery.KEY_QUERY_SCALE, scale); - return this; - } - - /** - * Sets the target {@link CurrencyUnit}, which defines a rounding targeting a concrete {@link - * CurrencyUnit}. - * Typically this determines all other properties, such as scale and the concrete rounding algorithm. With - * rounding names, depending on the implementation, additional subselections are possible. Similarly - * additional attributes can be used to select special rounding instances, e.g. for cash rounding. - * - * @param currencyUnit the target {@link CurrencyUnit} not null. - * @return this instance for chaining - */ - public RoundingQueryBuilder setCurrency(CurrencyUnit currencyUnit) { - Objects.requireNonNull(currencyUnit); - set(CurrencyUnit.class, currencyUnit); - return this; - } - - /** - * Creates a new instance of {@link javax.money.RoundingQuery}. - * - * @return a new {@link javax.money.RoundingQuery} instance. - */ - public RoundingQuery build() { - return new RoundingQuery(this); - } - - /** - * @return Creates a new RoundingQueryBuilder. - */ - public static RoundingQueryBuilder of() { - return new RoundingQueryBuilder(); - } - - /** - * Creates a new RoundingQueryBuilder. - * - * @param roundingQuery the rounding query, used as a template, not null. - * @return a new {@link javax.money.RoundingQueryBuilder} instance, never null. - */ - public static RoundingQueryBuilder of(RoundingQuery roundingQuery) { - return new RoundingQueryBuilder(roundingQuery); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/UnknownCurrencyException.java b/src/main/java/javax/money/UnknownCurrencyException.java deleted file mode 100644 index 75328ff34..000000000 --- a/src/main/java/javax/money/UnknownCurrencyException.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.Locale; -import java.util.Objects; - -/** - * Exception thrown when a currency code cannot be resolved into a {@link CurrencyUnit}. - * - * @author Werner Keil - * @author Anatole Tresch - * @version 0.8 - */ -public class UnknownCurrencyException extends MonetaryException { - - /** - * serialVersionUID. - */ - private static final long serialVersionUID = 1421993009305080653L; - /** The invalid currency code requested. */ - private final String currencyCode; - /** The invalid {@link Locale} requested. */ - private final Locale locale; - - /** - * Creates a new exception instance when a {@link CurrencyUnit} could not be evaluated given a - * currency code. - * - * @see Monetary#getCurrency(String, String...) - * @param code - * The unknown currency code (the message is constructed automatically), not null. - */ - public UnknownCurrencyException(String code) { - super("Unknown currency code: " + code); - this.currencyCode = code; - this.locale = null; - } - - /** - * Creates a new exception instance when a {@link CurrencyUnit} could not be evaluated given a - * (country) {@link Locale}. - * - * @see Monetary#getCurrency(Locale,String...) - * @param locale - * The unknown {@link Locale}, for which a {@link CurrencyUnit} was queried (the - * message is constructed automatically), not null. - */ - public UnknownCurrencyException(Locale locale) { - super("No currency for found for Locale: " + locale); - this.locale = locale; - this.currencyCode = null; - } - - /** - * Access the invalid currency code. - * - * @return the invalid currency code, or {@code null}. - */ - public String getCurrencyCode() { - return currencyCode; - } - - /** - * Access the invalid {@link Locale}. - * - * @return the invalid {@link Locale}, or {@code null}. - */ - public Locale getLocale() { - return locale; - } - - /* - * (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - if (Objects.isNull(locale)) { - return "UnknownCurrencyException [currencyCode=" + currencyCode + "]"; - } - else{ - return "UnknownCurrencyException [locale=" + locale + "]"; - } - } - -} diff --git a/src/main/java/javax/money/convert/ConversionContext.java b/src/main/java/javax/money/convert/ConversionContext.java deleted file mode 100644 index f08ad7a4e..000000000 --- a/src/main/java/javax/money/convert/ConversionContext.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.AbstractContext; - -/** - * This class models a context for which a {@link ExchangeRate} is valid. It allows to define - * different settings such as - *

    - *
  • the required {@link javax.money.convert.RateType},
  • - *
  • the required target timestamp
  • - *
  • the required validity duration
  • - *
  • additional non standard or extended attributes determined by the implementations participating in the - * ExchangeRateProvider chain.
  • - *
- * This class is immutable, thread-safe and serializable. - * - * @author Anatole Tresch - */ -public final class ConversionContext extends AbstractContext { - - private static final long serialVersionUID = 2386546659786888877L; - - /** - * ConversionContext that queries any conversion available. - */ - public static final ConversionContext ANY_CONVERSION = - new ConversionContextBuilder().setRateType(RateType.ANY).build(); - /** - * ConversionContext querying for any deferred rates. - */ - public static final ConversionContext DEFERRED_CONVERSION = - new ConversionContextBuilder().setRateType(RateType.DEFERRED).build(); - /** - * ConversionContext querying for any historic rates. - */ - public static final ConversionContext HISTORIC_CONVERSION = - new ConversionContextBuilder().setRateType(RateType.HISTORIC).build(); - /** - * ConversionContext querying for real-time rates. - */ - public static final ConversionContext REALTIME_CONVERSION = - new ConversionContextBuilder().setRateType(RateType.REALTIME).build(); - /** - * ConversionContext querying for any other rates. - */ - public static final ConversionContext OTHER_CONVERSION = - new ConversionContextBuilder().setRateType(RateType.OTHER).build(); - - /** - * Private constructor, used by {@link javax.money.convert.ConversionContextBuilder}. - * - * @param builder the Builder. - */ - ConversionContext(ConversionContextBuilder builder) { - super(builder); - } - - /** - * Get the deferred flag. Exchange rates can be deferred or real.time. - * - * @return the deferred flag, or {code null}. - */ - public RateType getRateType() { - return get(RateType.class); - } - - - /** - * Get the provider of this rate. The provider of a rate can have different - * contexts in different usage scenarios, such as the service type or the - * stock exchange. - * - * @return the provider, or {code null}. - */ - public String getProviderName() { - return getText("provider"); - } - - /** - * Creates a conversion query builder with the context data from this context instance. - * - * @return a corresponding conversion query builder instance, never null. - */ - public ConversionContextBuilder toBuilder() { - return ConversionContextBuilder.of(this); - } - - /** - * Creates a query builder based on this context. - * - * @return a new instance of {@link ConversionQueryBuilder}, never null. - */ - public ConversionQueryBuilder toQueryBuilder() { - return ConversionQueryBuilder.of().importContext(this); - } - - /** - * Simple factory method for {@link ConversionContext}. For more - * possibilities to initialize a {@link ConversionContext}, please use a - * {@link javax.money.convert.ConversionContextBuilder}, - * - * @param provider the provider name, not {@code null} - * @param rateType the required rate type. - * @return a new instance of {@link ConversionContext} - */ - public static ConversionContext of(String provider, RateType rateType) { - ConversionContextBuilder b = new ConversionContextBuilder(); - b.setRateType(rateType); - b.setProviderName(provider); - return b.build(); - } - - /** - * Creates a new ConversionContext for the given {@link ProviderContext} and the given {@link RateType}. - *

- * Note: for adding additional attributes use {@link javax.money.convert.ConversionContextBuilder - * (ProviderContext, RateType)}. - * - * @param providerContext the provider context, not null. - * @param rateType the rate type, not null. - * @return a corresponding instance of ConversionContext. - */ - public static ConversionContext from(ProviderContext providerContext, RateType rateType) { - return ConversionContextBuilder.create(providerContext, rateType).build(); - } - - /** - * Creates a {@link ConversionContext} for accessing rates of the given - * type, without specifying the rate's provider. - * - * @param rateType the required rate type. - * @return a new instance of {@link ConversionContext} - */ - public static ConversionContext of(RateType rateType) { - switch (rateType) { - case DEFERRED: - return DEFERRED_CONVERSION; - case HISTORIC: - return HISTORIC_CONVERSION; - case REALTIME: - return REALTIME_CONVERSION; - case OTHER: - return OTHER_CONVERSION; - case ANY: - default: - return ANY_CONVERSION; - } - } - - /** - * Simple factory method for {@link ConversionContext}. For more - * possibilities to initialize a {@link ConversionContext}, please use a - * {@link javax.money.convert.ConversionContextBuilder}, - * - * @return a new instance of {@link ConversionContext} - */ - public static ConversionContext of() { - return ANY_CONVERSION; - } - - -} diff --git a/src/main/java/javax/money/convert/ConversionContextBuilder.java b/src/main/java/javax/money/convert/ConversionContextBuilder.java deleted file mode 100644 index a25302048..000000000 --- a/src/main/java/javax/money/convert/ConversionContextBuilder.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.AbstractContextBuilder; -import java.util.Objects; - -/** - * Builder class to of {@link ConversionContext} instances. Instances of - * this class are not thread-safe. - * - * @author Anatole Tresch - */ -public final class ConversionContextBuilder extends AbstractContextBuilder { - - /** - * Create a new Builder, hereby using the given - * {@link ConversionContext}'s values as defaults. This allows changing - * an existing {@link ConversionContext} easily. - * - * @param context the context, not {@code null} - */ - private ConversionContextBuilder(ConversionContext context) { - importContext(context); - } - - /** - * Create a new Builder, hereby using the given - * {@link ConversionContext}'s values as defaults. This allows changing - * an existing {@link ConversionContext} easily. - * - * @param context the provider context, not {@code null} - * @param rateType the rate type, not null. - */ - private ConversionContextBuilder(ProviderContext context, RateType rateType) { - importContext(context); - setRateType(rateType); - } - - /** - * Set the historic value. - * - * @param rateType the rate type - * @return this, for chaining. - */ - public ConversionContextBuilder setRateType(RateType rateType) { - Objects.requireNonNull(rateType); - set(rateType); - return this; - } - - /** - * Creates a new {@link ConversionContext} with the data from this - * Builder instance. - * - * @return a new {@link ConversionContext}. never {@code null}. - */ - public ConversionContext build() { - return new ConversionContext(this); - } - - /** - * Create a new Builder instance without any provider, e.g. for creating - * new {@link ConversionContext} instances for querying. - */ - public ConversionContextBuilder() { - set(RateType.ANY); - } - - /** - * Creates a new {@link javax.money.convert.ConversionContextBuilder} instance. - * @param conversionContext the conversion context to be used to initialize the new builder instance, not null. - * @return a new {@link javax.money.convert.ConversionContextBuilder} instance, never null. - */ - public static ConversionContextBuilder of(ConversionContext conversionContext) { - return new ConversionContextBuilder(conversionContext); - } - - /** - * Creates a new {@link javax.money.convert.ConversionContextBuilder} instance. - * - * @return a new {@link javax.money.convert.ConversionContextBuilder} instance, never null. - */ - public static ConversionContextBuilder of() { - return new ConversionContextBuilder(); - } - - /** - * Create a new Builder, hereby using the given - * {@link ConversionContext}'s values as defaults. This allows changing - * an existing {@link ConversionContext} easily. - * - * @param context the provider context, not {@code null} - * @param rateType the rate type, not null. - * @return a new {@link javax.money.convert.ConversionContextBuilder} instance, never null. - */ - public static ConversionContextBuilder create(ProviderContext context, RateType rateType) { - return new ConversionContextBuilder(context, rateType); - } - -} diff --git a/src/main/java/javax/money/convert/ConversionQuery.java b/src/main/java/javax/money/convert/ConversionQuery.java deleted file mode 100644 index 9df79b3e1..000000000 --- a/src/main/java/javax/money/convert/ConversionQuery.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.AbstractQuery; -import javax.money.CurrencySupplier; -import javax.money.CurrencyUnit; -import java.util.*; - -/** - * Query for accessing {@link javax.money.convert.CurrencyConversion} instances. If not properties are set the query - * should returns the default currencies. - *

- * This class is immutable, serializable and thread-safe. - *

- */ -public final class ConversionQuery extends AbstractQuery implements CurrencySupplier { - /** - * serialVersionUID. - */ - private static final long serialVersionUID = -9147265628185601586L; - - - /** - * THe key used for the base currency attribute. - */ - static final String KEY_BASE_CURRENCY = "Query.baseCurrency"; - - /** - * THe key used for the term currency attribute. - */ - static final String KEY_TERM_CURRENCY = "Query.termCurrency"; - - /** - * THe key used for the rate types attribute. - */ - static final String KEY_RATE_TYPES = "Query.rateTypes"; - - /** - * Constructor, used from the ConversionQueryBuilder. - * - * @param builder the corresponding builder, not null. - */ - ConversionQuery(ConversionQueryBuilder builder) { - super(builder); - } - - /** - * Get the rate types set. - * - * @return the rate types set, or an empty array, but never null. - */ - @SuppressWarnings("unchecked") - public Set getRateTypes() { - Set result = get(KEY_RATE_TYPES, Set.class); - if (result == null) { - return Collections.emptySet(); - } - return result; - } - - /** - * Get the base currency. This attribute is optional, when a {@link javax.money.convert.CurrencyConversion} - * is accessed. It is optional if accessing instances of {@link javax.money.convert.ExchangeRateProvider}. If set - * it can constraint - * a {@link javax.money.convert.CurrencyConversion} or {@link javax.money.convert.ExchangeRateProvider} to - * only support one type of base currency. By default it is not set, hereby determining the base currency by the - * amount onto which the conversion is applied. - * - * @return the base CurrencyUnit, or null. - */ - public CurrencyUnit getBaseCurrency() { - return get(KEY_BASE_CURRENCY, CurrencyUnit.class); - } - - /** - * Get the terminating currency. This attribute is required, when a {@link javax.money.convert.CurrencyConversion} - * is accessed. It is optional if accessing instances of {@link javax.money.convert.ExchangeRateProvider}. - * - * @return the terminating CurrencyUnit, or null. - */ - public CurrencyUnit getCurrency() { - return get(KEY_TERM_CURRENCY, CurrencyUnit.class); - } - - /** - * Creates a new Builder preinitialized with values from this instance. - * - * @return a new Builder, never null. - */ - public ConversionQueryBuilder toBuilder() { - return ConversionQueryBuilder.of(this); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/convert/ConversionQueryBuilder.java b/src/main/java/javax/money/convert/ConversionQueryBuilder.java deleted file mode 100644 index 44c60d6e7..000000000 --- a/src/main/java/javax/money/convert/ConversionQueryBuilder.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.AbstractQueryBuilder; -import javax.money.CurrencyUnit; -import javax.money.Monetary; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * Builder class for creating new instances of {@link javax.money.convert.ConversionQuery} adding detailed - * information about a {@link javax.money.convert.CurrencyConversion} instance. - *

- * Note this class is NOT thread-safe. - * - * @see javax.money.convert.MonetaryConversions#getConversion(ConversionQuery) - */ -public final class ConversionQueryBuilder extends AbstractQueryBuilder { - - private ConversionQueryBuilder() { - } - - /** - * Set the providers to be considered. If not set explicitly the default ISO currencies as - * returned by {@link java.util.Currency} is used. - * - * @param rateTypes the rate types to use, not null. - * @return the query for chaining. - */ - public ConversionQueryBuilder setRateTypes(RateType... rateTypes) { - return set(ConversionQuery.KEY_RATE_TYPES, new HashSet<>(Arrays.asList(rateTypes))); - } - - /** - * Set the providers to be considered. If not set explicitly the default ISO currencies as - * returned by {@link java.util.Currency} is used. - * - * @param rateTypes the rate types to use, not null. - * @return the query for chaining. - */ - public ConversionQueryBuilder setRateTypes(Set rateTypes) { - return set(ConversionQuery.KEY_RATE_TYPES, rateTypes); - } - - /** - * Sets the base currency. - * - * @param currency the base currency - * @return the query for chaining. - */ - public ConversionQueryBuilder setBaseCurrency(CurrencyUnit currency) { - return set(ConversionQuery.KEY_BASE_CURRENCY, currency); - } - - /** - * Sets the base currency. - * - * @param currencyCode the currency code, resolvable through {@link javax.money - * .MonetaryCurrencies#getCurrency(String, String...)}, not null. - * @return the query for chaining. - */ - public ConversionQueryBuilder setBaseCurrency(String currencyCode) { - return setBaseCurrency(Monetary.getCurrency(currencyCode)); - } - - /** - * Sets the term currency. - * - * @param currency the base currency - * @return the query for chaining. - */ - public ConversionQueryBuilder setTermCurrency(CurrencyUnit currency) { - return set(ConversionQuery.KEY_TERM_CURRENCY, currency); - } - - /** - * Sets the term currency. - * - * @param currencyCode the currency code, resolvable through {@link javax.money - * .MonetaryCurrencies#getCurrency(String, String...)}, not null. - * @return the query for chaining. - */ - public ConversionQueryBuilder setTermCurrency(String currencyCode) { - return setTermCurrency(Monetary.getCurrency(currencyCode)); - } - - /** - * Creates a new instance of {@link ConversionQuery}. - * - * @return a new {@link ConversionQuery} instance. - */ - @Override - public ConversionQuery build() { - return new ConversionQuery(this); - } - - /** - * Creates a new {@link javax.money.convert.ConversionQueryBuilder} instance. - * - * @return a new {@link javax.money.convert.ConversionQueryBuilder} instance, never null. - */ - public static ConversionQueryBuilder of() { - return new ConversionQueryBuilder(); - } - - /** - * Creates a new {@link javax.money.convert.ConversionQueryBuilder} instance. - * - * @param query the {@link javax.money.convert.ConversionQuery} instance to be used as a template. - * @return a new {@link javax.money.convert.ConversionQueryBuilder} instance, never null. - */ - public static ConversionQueryBuilder of(ConversionQuery query) { - return new ConversionQueryBuilder().importContext(query); - } - -} diff --git a/src/main/java/javax/money/convert/CurrencyConversion.java b/src/main/java/javax/money/convert/CurrencyConversion.java deleted file mode 100644 index f5020e187..000000000 --- a/src/main/java/javax/money/convert/CurrencyConversion.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.*; - -/** - * This interface defines a {@link CurrencyConversion} that is converting a {@link MonetaryAmount} to another - * {@link MonetaryAmount} with a different target {@link CurrencyUnit}. Each instance of this class is bound to - * a specific {@link ExchangeRateProvider} (or a chain of rate providers), a term {@link CurrencyUnit} and - * (optionally) a target timestamp. Additionally the {@link javax.money.convert.ConversionContext} can have additional - * attributes set that are passed to the rate provider (chain). - *

- * This interface serves a an API for the clients, but also must be implemented - * and registered as SPI to the mechanisms required by the - * {@link javax.money.spi.MonetaryConversionsSingletonSpi} implementation. - *

- * By extending {@link MonetaryOperator} currency conversion can simply be applied on each {@link MonetaryAmount} - * calling the amount'0s with method: - *


- *     MonetaryAmount amount = ...;
- *     CurrencyConversion conversion = MonetaryConversions.getConversion("CHF");
- *     MonetaryAmount amountInCHF = amount.with(conversion);
- * 
- *

- * The terminating {@link CurrencyUnit} of this conversion instance can be - * accessed from {@code getCurrency()}, inherited from {@code CurrencySupplier}. - *

- * Instances of this class are required to be thread-safe, but it is not a - * requirement that they are serializable. In a EE context they can be - * implemented using contextual beans. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public interface CurrencyConversion extends MonetaryOperator, CurrencySupplier { - - /** - * Access the target {@link ConversionContext} of this conversion instance. - * - * @return the target {@link ConversionContext}. - */ - ConversionContext getContext(); - - /** - * Get the {@link ExchangeRate} applied for the given {@link MonetaryAmount} - * . - * - * @param sourceAmount the amount to be converted. - * @return the {@link ExchangeRate} applied. - * @throws MonetaryException if the amount can not be converted. - */ - ExchangeRate getExchangeRate(MonetaryAmount sourceAmount); - - /** - * Access the underlying {@link javax.money.convert.ExchangeRateProvider}. - * - * @return the underlying {@link javax.money.convert.ExchangeRateProvider}, never null. - */ - ExchangeRateProvider getExchangeRateProvider(); - -} diff --git a/src/main/java/javax/money/convert/CurrencyConversionException.java b/src/main/java/javax/money/convert/CurrencyConversionException.java deleted file mode 100644 index 71222ee09..000000000 --- a/src/main/java/javax/money/convert/CurrencyConversionException.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.CurrencyUnit; -import javax.money.MonetaryException; -import java.util.Objects; - -/** - * Exception thrown when a monetary conversion operation fails. - * - * @author Werner Keil - * @author Stephen Colebourne - * @author Anatole Tresch - */ -public class CurrencyConversionException extends MonetaryException { - - /** - * Serialization lock. - */ - private static final long serialVersionUID = -7743240650686883450L; - - /** - * Base currency. - */ - private final CurrencyUnit base; - /** - * Terminating currency. - */ - private final CurrencyUnit term; - /** - * The acquired {@link ConversionContext}, may be null. - */ - private final ConversionContext conversionContext; - - /** - * Constructs an CurrencyConversionException with the specified - * detail message, timestamp, source and target currency. - * - * @param base the source currency, may be null. - * @param term the target currency, may be null. - * @param conversionContext the {@link javax.money.convert.ConversionContext} in place. - * @param message the detail message. - */ - public CurrencyConversionException(CurrencyUnit base, CurrencyUnit term, - ConversionContext conversionContext, String message) { - super("Cannot convert " + String.valueOf(base) + " into " - + String.valueOf(term) + ": " + message); - this.base = base; - this.term = term; - this.conversionContext = conversionContext; - } - - /** - * Constructs an CurrencyConversionException with the specified - * source and target currency. - * - * @param base the source currency, may be null. - * @param term the target currency, may be null. - * @param conversionContext the {@link javax.money.convert.ConversionContext} in place. - */ - public CurrencyConversionException(CurrencyUnit base, CurrencyUnit term, - ConversionContext conversionContext) { - super("Cannot convert " + String.valueOf(base) + " into " - + String.valueOf(term)); - this.base = base; - this.term = term; - this.conversionContext = conversionContext; - } - - /** - * Constructs a new exception with the specified source and target currency, - * detail message and cause. - *

- * Note that the detail message associated with cause is - * not automatically incorporated in this exception's detail message. - *

- * - * @param base the source currency, may be null. - * @param term the target currency, may be null. - * @param message the detail message (which is saved for later retrieval by the - * {@link Throwable#getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the - * {@link Throwable#getCause()} method). (A null value - * is permitted, and indicates that the cause is nonexistent or - * unknown.) - * @param conversionContext the {@link javax.money.convert.ConversionContext} in place. - */ - public CurrencyConversionException(CurrencyUnit base, CurrencyUnit term, - ConversionContext conversionContext, String message, Throwable cause) { - super("Cannot convert " + String.valueOf(base) + " into " - + String.valueOf(term) - + (Objects.nonNull(message) ? ": " + message : ""), cause); - this.base = base; - this.term = term; - this.conversionContext = conversionContext; - } - - /** - * Gets the first currency at fault. - * - * @return the currency at fault, may be null - */ - public CurrencyUnit getBaseCurrency() { - return base; - } - - /** - * Gets the second currency at fault. - * - * @return the currency at fault, may be null - */ - public CurrencyUnit getTermCurrency() { - return term; - } - - /** - * Gets the queried timestamp at fault. - * - * @return the queried timestamp, or {@code null}. - */ - public ConversionContext getConversionContext() { - return this.conversionContext; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "CurrencyConversionException [base=" + base + ", term=" + term - + ", conversionContext=" + conversionContext + "]: " - + getMessage(); - } - -} diff --git a/src/main/java/javax/money/convert/ExchangeRate.java b/src/main/java/javax/money/convert/ExchangeRate.java deleted file mode 100644 index 4d7d2e310..000000000 --- a/src/main/java/javax/money/convert/ExchangeRate.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.CurrencySupplier; -import javax.money.CurrencyUnit; -import javax.money.NumberValue; -import java.io.Serializable; -import java.util.List; - -/** - * This class models an exchange rate, which defines the factor the numeric value of a base amount in some currency - * 'A' must be multiplied - * to get the corresponding amount in the terminating currency 'B'. Hereby - *
    - *
  • an exchange rate always models one rate from a base (source) to a term - * (target) {@link CurrencyUnit}.
  • - *
  • an exchange rate is always bound to a rate type, which typically matches - * the data source of the conversion data, e.g. different credit card providers - * may use different rates for the same conversion.
  • - *
  • an exchange rate may restrict its validity. In most of the use cases a - * rates' validity will be well defined, but it is also possible that the data - * provider is not able to support the rate's validity, leaving it undefined-
  • - *
  • an exchange rate has a provider, which is responsible for defining the - * rate. A provider hereby may be, but must not be the same as the rate's data - * source.
  • - *
  • an exchange rate can be a direct rate, where its factor is - * represented by a single conversion step. Or it can model a derived - * rate, where multiple conversion steps are required to define the overall - * base/term conversion. In case of derived rates the chained rates define the - * overall factor, by multiplying the individual chain rate factors. Of course, - * this also requires that each subsequent rate's base currency in the chain - * does match the previous term currency (and vice versa):
  • - *
  • Whereas the factor should be directly implied by the format rate chain - * for derived rates, this is obviously not the case for the validity range, - * since rates can have a undefined validity range. Nevertheless in many cases - * also the validity range can (but must not) be derived from the rate chain.
  • - *
  • Finally a conversion rate is always unidirectional. There might be cases - * where the reciprocal value of {@link #getFactor()}} matches the correct reverse - * rate. But in most use cases the reverse rate either has a different rate (not - * equal to the reciprocal value), or might not be defined at all. Therefore for - * reversing a ExchangeRate one must access an {@link ExchangeRateProvider} and - * query for the reverse rate.
  • - *
- *

- * The class also implements {@link Comparable} to allow sorting of multiple - * exchange rates using the following sorting order; - *

- *
    - *
  • Exchange rate type
  • - *
  • Exchange rate provider
  • - *
  • base currency
  • - *
  • term currency
  • - *
- *

- * Finally ExchangeRate is modeled as an immutable and thread safe type. Also - * exchange rates are {@link Serializable}, hereby serializing in the following - * form and order: - *

- *
    - *
  • The base {@link CurrencyUnit}
  • - *
  • The target {@link CurrencyUnit}
  • - *
  • The factor (NumberValue)
  • - *
  • The {@link ConversionContext}
  • - *
  • The rate chain
  • - *
- *

Implementation Specification

- *

Implementations of this interface

- *
    - *
  • must be Comparable(with {@code ExchangeRate})
  • - *
  • must implement equals/hashCode considering #getBaseCurrency, #getCurrency, - * #getFactor and #getContext.
  • - *
  • should be thread-safe
  • - *
  • should be serializable
  • - *
  • should provide a fluent builder API for constructing new rate instances easily.
  • - *
- * - * @author Werner Keil - * @author Anatole Tresch - * @see Wikipedia: - * Exchange Rate (Quotations) - */ -public interface ExchangeRate extends CurrencySupplier { - - /** - * Access the {@link ConversionContext} of {@link ExchangeRate}. - * - * @return the conversion context, never null. - */ - ConversionContext getContext(); - - /** - * Get the base (source) {@link CurrencyUnit}. - * - * @return the base {@link CurrencyUnit}. - */ - CurrencyUnit getBaseCurrency(); - - /** - * Get the term (target) {@link CurrencyUnit}. - * - * @return the term {@link CurrencyUnit}. - */ - @Override - CurrencyUnit getCurrency(); - - /** - * Access the rate's bid factor. - * - * @return the bid factor for this exchange rate, or {@code null}. - */ - NumberValue getFactor(); - - /** - * Access the chain of exchange rates. - * - * @return the chain of rates, in case of a derived rate, this may be - * several instances. For a direct exchange rate, this equals to - * new ExchangeRate[]{this}. - */ - List getExchangeRateChain(); - - /** - * Allows to evaluate if this exchange rate is a derived exchange rate. - * Derived exchange rates are defined by an ordered list of subconversions - * with intermediate steps, whereas a direct conversion is possible in one - * steps. - *

- * This method always returns {@code true}, if the chain contains more than - * one rate. Direct rates, have also a chain, but with exact one rate. - * - * @return true, if the exchange rate is derived. - */ - default boolean isDerived() { - return getExchangeRateChain().size() > 1; - } - -} diff --git a/src/main/java/javax/money/convert/ExchangeRateProvider.java b/src/main/java/javax/money/convert/ExchangeRateProvider.java deleted file mode 100644 index 88c257b7f..000000000 --- a/src/main/java/javax/money/convert/ExchangeRateProvider.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.*; -import java.util.Objects; - -/** - * This interface defines access to the exchange rates provided by a provider. - * The provider and its capabilities can be defined in arbitrary detail by the - * corresponding {@link javax.money.convert.ProviderContext}. - * Instances of this class must only provide conversion data for exact one provider, identified by - * {@link ProviderContext#getProviderName()}. - * - * When accessing ExchangeRateProvider instances or {@link javax.money.convert.CurrencyConversion} instances from the - * {@link MonetaryConversions} - * in many cases a chain of providers will be returned. It is the responsibility of the implementation code assembling - * the chain to - * establish a well defined coordination mechanism for evaluating the correct result. By default the first provider - * in the chain that returns a non null result determines the final result of a call. Nevertheless adapting the - * {@link javax.money.spi.MonetaryConversionsSingletonSpi} allows - * to implement also alternate strategies, e.g. honoring different priorities of providers as well. - *

- * Implementations of this interface are required to be thread save. - *

- * Implementations of this class must neither be immutable nor serializable. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public interface ExchangeRateProvider{ - - /** - * Access the {@link ConversionContext} for this - * {@link ExchangeRateProvider}. Each instance of - * {@link ExchangeRateProvider} provides conversion data for exact one - * {@link ConversionContext} . - * - * @return the exchange rate type, never {@code null}. - */ - ProviderContext getContext(); - - /** - * Access a {@link ExchangeRate} using the given currencies. The - * {@link ExchangeRate} may be, depending on the data provider, real-time or - * deferred. This method should return the rate that is currently - * valid. - * - * @param conversionQuery the required {@link ConversionQuery}, not {@code null} - * @return the matching {@link ExchangeRate}. - * @throws CurrencyConversionException If no such rate is available. - * @throws MonetaryException if one of the currency codes passed is not valid. - * @see javax.money.convert.ConversionQueryBuilder - */ - ExchangeRate getExchangeRate(ConversionQuery conversionQuery); - - /** - * Access a {@link CurrencyConversion} that can be applied as a - * {@link MonetaryOperator} to an amount. - * - * @param conversionQuery the required {@link ConversionQuery}, not {@code null} - * @return a new instance of a corresponding {@link CurrencyConversion}, - * never {@code null}. - * @throws MonetaryException if one of the currency codes passed is not valid. - * @see javax.money.convert.ConversionQueryBuilder - */ - CurrencyConversion getCurrencyConversion(ConversionQuery conversionQuery); - - - /** - * Checks if an {@link ExchangeRate} between two {@link CurrencyUnit} is - * available from this provider. This method should check, if a given rate - * is currently defined. - * - * @param conversionQuery the required {@link ConversionQuery}, not {@code null} - * @return {@code true}, if such an {@link ExchangeRate} is currently - * defined. - */ - default boolean isAvailable(ConversionQuery conversionQuery){ - Objects.requireNonNull(conversionQuery); - try{ - return conversionQuery.getProviderNames().isEmpty() || - conversionQuery.getProviderNames().contains(getContext().getProviderName()); - } - catch(Exception e){ - return false; - } - } - - - /** - * Access a {@link ExchangeRate} using the given currencies. The - * {@link ExchangeRate} may be, depending on the data provider, real-time or - * deferred. This method should return the rate that is currently - * valid. - * - * @param base base {@link CurrencyUnit}, not {@code null} - * @param term term {@link CurrencyUnit}, not {@code null} - * @return the matching {@link ExchangeRate}. - * @throws CurrencyConversionException If no such rate is available. - */ - default ExchangeRate getExchangeRate(CurrencyUnit base, CurrencyUnit term){ - Objects.requireNonNull(base, "Base Currency is null"); - Objects.requireNonNull(term, "Term Currency is null"); - return getExchangeRate(ConversionQueryBuilder.of().setBaseCurrency(base).setTermCurrency(term).build()); - } - - /** - * Access a {@link CurrencyConversion} that can be applied as a - * {@link MonetaryOperator} to an amount. - * - * @param term term {@link CurrencyUnit}, not {@code null} - * @return a new instance of a corresponding {@link CurrencyConversion}, - * never {@code null}. - */ - default CurrencyConversion getCurrencyConversion(CurrencyUnit term){ - return getCurrencyConversion(ConversionQueryBuilder.of().setTermCurrency(term).build()); - } - - /** - * Checks if an {@link ExchangeRate} between two {@link CurrencyUnit} is - * available from this provider. This method should check, if a given rate - * is currently defined. - * - * @param base the base {@link CurrencyUnit} - * @param term the term {@link CurrencyUnit} - * @return {@code true}, if such an {@link ExchangeRate} is currently - * defined. - */ - default boolean isAvailable(CurrencyUnit base, CurrencyUnit term){ - return isAvailable(ConversionQueryBuilder.of().setBaseCurrency(base).setTermCurrency(term).build()); - } - - - /** - * Checks if an {@link ExchangeRate} between two {@link CurrencyUnit} is - * available from this provider. This method should check, if a given rate - * is currently defined. - * - * @param baseCode the base currency code - * @param termCode the terminal/target currency code - * @return {@code true}, if such an {@link ExchangeRate} is currently - * defined. - * @throws MonetaryException if one of the currency codes passed is not valid. - */ - default boolean isAvailable(String baseCode, String termCode){ - return isAvailable(Monetary.getCurrency(baseCode), Monetary.getCurrency(termCode)); - } - - - /** - * Access a {@link ExchangeRate} using the given currencies. The - * {@link ExchangeRate} may be, depending on the data provider, real-time or - * deferred. This method should return the rate that is currently - * valid. - * - * @param baseCode base currency code, not {@code null} - * @param termCode term/target currency code, not {@code null} - * @return the matching {@link ExchangeRate}. - * @throws CurrencyConversionException If no such rate is available. - * @throws MonetaryException if one of the currency codes passed is not valid. - */ - default ExchangeRate getExchangeRate(String baseCode, String termCode){ - return getExchangeRate(Monetary.getCurrency(baseCode), Monetary.getCurrency(termCode)); - } - - - /** - * The method reverses the {@link ExchangeRate} to a rate mapping from term - * to base {@link CurrencyUnit}. Hereby the factor must not be - * recalculated as {@code 1/oldFactor}, since typically reverse rates are - * not symmetric in most cases. - * - * @param rate {@link ExchangeRate}, not {@code null} - * @return the matching reversed {@link ExchangeRate}, or {@code null}, if - * the rate cannot be reversed. - */ - default ExchangeRate getReversed(ExchangeRate rate){ - ConversionQuery reverseQuery = rate.getContext().toQueryBuilder().setBaseCurrency(rate.getCurrency()) - .setTermCurrency(rate.getBaseCurrency()).build(); - if(isAvailable(reverseQuery)){ - return getExchangeRate(reverseQuery); - } - return null; - } - - - /** - * Access a {@link CurrencyConversion} that can be applied as a - * {@link MonetaryOperator} to an amount. - * - * @param termCode terminal/target currency code, not {@code null} - * @return a new instance of a corresponding {@link CurrencyConversion}, - * never {@code null}. - * @throws MonetaryException if one of the currency codes passed is not valid. - */ - default CurrencyConversion getCurrencyConversion(String termCode){ - return getCurrencyConversion(Monetary.getCurrency(termCode)); - } - -} diff --git a/src/main/java/javax/money/convert/ExchangeRateProviderSupplier.java b/src/main/java/javax/money/convert/ExchangeRateProviderSupplier.java deleted file mode 100644 index a20bbc4a5..000000000 --- a/src/main/java/javax/money/convert/ExchangeRateProviderSupplier.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* -* CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE -* CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. -* PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY -* DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE -* AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" -* BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency -* API ("Specification") Copyright (c) 2012-2015, Credit SUISSE All rights -* reserved. -*/ -package javax.money.convert; - - -/** - * A supplier of {@link ExchangeRateProvider} name that references an implementation. This can be used to let - * an enum type implement this interface, so enums values can be passed to {@link javax.money.convert.MonetaryConversions} - * for determining the rate providers to be used. - */ -@FunctionalInterface -public interface ExchangeRateProviderSupplier{ - - /** - * Get the provider name. This signature equals to the signature of java.util.function.Supplier in Java 8. - * - * @return the provider name, not null. - */ - String get(); - -} diff --git a/src/main/java/javax/money/convert/MonetaryConversions.java b/src/main/java/javax/money/convert/MonetaryConversions.java deleted file mode 100644 index 2e0efa8f1..000000000 --- a/src/main/java/javax/money/convert/MonetaryConversions.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.ServiceLoader; -import java.util.logging.Logger; - -import javax.money.CurrencyUnit; -import javax.money.Monetary; -import javax.money.MonetaryException; -import javax.money.spi.Bootstrap; -import javax.money.spi.MonetaryConversionsSingletonSpi; - -/** - * This singleton defines access to the exchange and currency conversion logic - * of JavaMoney. It allows to evaluate the currently available exchange rate - * type instances and provides access to the corresponding - * {@link ExchangeRateProvider} and {@link javax.money.convert.CurrencyConversion} instances. - *

- * This class is thread safe. - *

- * This class is designed to support also contextual behaviour, e.g. in Java EE - * containers each application may provide its own {@link ExchangeRateProvider} - * instances, e.g. by registering them as CDI beans. An EE container can - * register an according {@link javax.money.spi.MonetaryConversionsSingletonSpi} that manages the - * different application contexts transparently. In a SE environment this class - * is expected to behave like an ordinary singleton, loading its SPIs e.g. from the - * JDK {@link ServiceLoader} or an alternate component and service provider. - *

- * This class is thread-safe. Hereby it is important to know that it delegates - * to the registered {@link javax.money.spi.MonetaryConversionsSingletonSpi} SPI, which also is required - * to be thread-safe. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public final class MonetaryConversions{ - - /** - * The SPI currently active, use {@link ServiceLoader} to register an - * alternate implementation. - */ - private static MonetaryConversionsSingletonSpi getMonetaryConversionsSpi() { - return Optional.ofNullable(Bootstrap.getService(MonetaryConversionsSingletonSpi.class)) - .orElseThrow(() -> new MonetaryException("No MonetaryConversionsSingletonSpi " + - "loaded, " + - "query functionality is not " + - "available.")); - } - - /** - * Private singleton constructor. - */ - private MonetaryConversions(){ - } - - /** - * Access an instance of {@link CurrencyConversion} for the given providers. - * Use {@link #getConversionProviderNames()} to check, which are available. - * - * @param termCurrency the terminating or target currency, not {@code null} - * @param providers Additional providers, for building a provider chain - * @return the exchange rate type if this instance. - * @throws IllegalArgumentException if no such {@link ExchangeRateProvider} is available. - */ - public static CurrencyConversion getConversion(CurrencyUnit termCurrency, String... providers){ - Objects.requireNonNull(providers); - Objects.requireNonNull(termCurrency); - if(providers.length == 0){ - return getMonetaryConversionsSpi().getConversion( - ConversionQueryBuilder.of().setTermCurrency(termCurrency).setProviderNames(getDefaultConversionProviderChain()) - .build()); - } - return getMonetaryConversionsSpi().getConversion( - ConversionQueryBuilder.of().setTermCurrency(termCurrency).setProviderNames(providers).build()); - } - - /** - * Access an instance of {@link CurrencyConversion} for the given providers. - * Use {@link #getConversionProviderNames()}} to check, which are available. - * - * @param termCurrencyCode the terminating or target currency code, not {@code null} - * @param providers Additional providers, for building a provider chain - * @return the exchange rate type if this instance. - * @throws MonetaryException if no such {@link ExchangeRateProvider} is available or if no {@link CurrencyUnit} was - * matching the given currency code. - */ - public static CurrencyConversion getConversion(String termCurrencyCode, String... providers){ - Objects.requireNonNull(termCurrencyCode, "Term currency code may not be null"); - return getConversion(Monetary.getCurrency(termCurrencyCode), providers); - } - - /** - * Access an instance of {@link CurrencyConversion} for the given providers. - * Use {@link #getConversionProviderNames()}} to check, which are available. - * - * @param conversionQuery The {@link ConversionQuery} required, not {@code null} - * @return the {@link CurrencyConversion} instance matching. - * @throws IllegalArgumentException if the query defines {@link ExchangeRateProvider}s that are not available. - */ - public static CurrencyConversion getConversion(ConversionQuery conversionQuery){ - return getMonetaryConversionsSpi().getConversion(conversionQuery); - } - - /** - * Checks if a {@link javax.money.convert.CurrencyConversion} is available for the given parameters. - * - * @param conversionQuery the {@link javax.money.convert.ConversionQuery}, not null. - * @return true, if a conversion is accessible from {@link #getConversion(ConversionQuery)}. - */ - public static boolean isConversionAvailable(ConversionQuery conversionQuery){ - return getMonetaryConversionsSpi().isConversionAvailable(conversionQuery); - } - - /** - * Checks if a {@link javax.money.convert.CurrencyConversion} is available for the given parameters. - * - * @param currencyCode The currency code, resolvable by {@link javax.money.Monetary#getCurrency - * (String, String...)} - * @param providers Additional providers, for building a provider chain - * @return true, if a conversion is accessible from {@link #getConversion(String, String...)}. - */ - public static boolean isConversionAvailable(String currencyCode, String... providers){ - return getMonetaryConversionsSpi() - .isConversionAvailable(Monetary.getCurrency(currencyCode), providers); - } - - /** - * Checks if a {@link javax.money.convert.CurrencyConversion} is available for the given parameters. - * - * @param termCurrency the terminating or target currency, not {@code null} - * @param providers Additional providers, for building a provider chain - * @return true, if a conversion is accessible from {@link #getConversion(String, String...)}. - */ - public static boolean isConversionAvailable(CurrencyUnit termCurrency, String... providers){ - return getMonetaryConversionsSpi() - .isConversionAvailable(termCurrency, providers); - } - - /** - * Access an instance of {@link CurrencyConversion} using the given - * providers as a provider chain. Use {@link #getConversionProviderNames()}s - * to check, which are available. - * - * @param providers Additional providers, for building a provider chain - * @return the exchange rate provider. - * @throws IllegalArgumentException if no such {@link ExchangeRateProvider} is available. - */ - public static ExchangeRateProvider getExchangeRateProvider(String... providers){ - if(providers.length == 0){ - List defaultProviderChain = getDefaultConversionProviderChain(); - return getMonetaryConversionsSpi().getExchangeRateProvider(ConversionQueryBuilder.of().setProviderNames( - defaultProviderChain.toArray(new String[defaultProviderChain.size()])).build()); - } - ExchangeRateProvider provider = getMonetaryConversionsSpi() - .getExchangeRateProvider(ConversionQueryBuilder.of().setProviderNames(providers).build()); - return Optional.ofNullable(provider) - .orElseThrow(() -> new MonetaryException("No such rate provider: " + Arrays.toString(providers))); - } - - /** - * Access an instance of {@link CurrencyConversion} using the - * {@link ExchangeRateProviderSupplier}. - * - * @param provider - * the exchange rate provider. - * @param providers - * the exchange rate provider. - * @return the exchange rate provider. - * @throws IllegalArgumentException - * if no such {@link ExchangeRateProvider} is available. - */ - public static ExchangeRateProvider getExchangeRateProvider( - ExchangeRateProviderSupplier provider, - ExchangeRateProviderSupplier... providers) { - - List suppliers = new ArrayList<>(); - suppliers.add(Objects.requireNonNull(provider)); - suppliers.addAll(Arrays.asList(providers)); - - String[] array = suppliers.stream() - .map(ExchangeRateProviderSupplier::get).toArray(String[]::new); - return getExchangeRateProvider(array); - - } - /** - * Access an instance of {@link CurrencyConversion} using the given - * providers as a provider chain. Use {@link #getConversionProviderNames()} - * to check, which are available. - * - * @param conversionQuery the {@link javax.money.convert.ConversionQuery}, not null. - * @return the exchange rate provider. - * @throws IllegalArgumentException if no such {@link ExchangeRateProvider} is available. - */ - public static ExchangeRateProvider getExchangeRateProvider(ConversionQuery conversionQuery){ - return getMonetaryConversionsSpi() - .getExchangeRateProvider(conversionQuery); - } - - /** - * Checks if a {@link javax.money.convert.ExchangeRateProvider} is available for the given parameters. - * - * @param conversionQuery the {@link javax.money.convert.ConversionQuery}, not null. - * @return true, if a rate provider is accessible from {@link #getExchangeRateProvider(ConversionQuery)}}. - */ - public static boolean isExchangeRateProviderAvailable(ConversionQuery conversionQuery){ - return getMonetaryConversionsSpi() - .isExchangeRateProviderAvailable(conversionQuery); - } - - - /** - * Return the (non localized) names of all providers available in the - * current context. Each id can be used to obtain - * {@link ExchangeRateProvider} or {@link CurrencyConversion} instances. - * - * @return all supported provider ids, never {@code null}. - */ - public static Collection getConversionProviderNames(){ - Collection providers = getMonetaryConversionsSpi().getProviderNames(); - if(Objects.isNull(providers)){ - Logger.getLogger(MonetaryConversions.class.getName()).warning( - "No supported rate/conversion providers returned by SPI: " + - getMonetaryConversionsSpi().getClass().getName()); - return Collections.emptySet(); - } - return providers; - } - - /** - * Get the default provider used. - * - * @return the default provider, never {@code null}. - */ - public static List getDefaultConversionProviderChain(){ - List defaultChain = getMonetaryConversionsSpi() - .getDefaultProviderChain(); - Objects.requireNonNull(defaultChain, "No default provider chain provided by SPI: " + - getMonetaryConversionsSpi().getClass().getName()); - return defaultChain; - } - -} diff --git a/src/main/java/javax/money/convert/ProviderContext.java b/src/main/java/javax/money/convert/ProviderContext.java deleted file mode 100644 index 01ee632da..000000000 --- a/src/main/java/javax/money/convert/ProviderContext.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import java.util.Collections; -import java.util.Set; - -import javax.money.AbstractContext; - -/** - * This class describes what kind of {@link javax.money.convert.ExchangeRate}s a {@link javax.money.convert - * .ExchangeRateProvider} delivers, including the provider's name, rate type and additional data. - * By default such a context supports the following attributes: - *

    - *
  • a unique non localizable provider name. This provider name is also used to identify a concrete instance of - * ExchangeRateProvider.
  • - *
  • a set of {@link javax.money.convert.RateType} an ExchangeRateProvider supports
  • - *
  • a time range for which an ExchangeRateProvider delivers rates.
  • - *
- * Additionally a instance of ProviderContext can have arbitrary additional attributes describing more precisely - * the capabilities of a concrete {@link }ExchangeRateProvider} implementation. - *

- * Instances of this class are immutable and thread-safe. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public final class ProviderContext extends AbstractContext { - - private static final long serialVersionUID = 3536713139786856877L; - - /** - * Key used for the rate types attribute. - */ - static final String KEY_RATE_TYPES = "rateTypes"; - - - /** - * Private constructor, used by {@link ProviderContextBuilder}. - * - * @param builder the Builder. - */ - ProviderContext(ProviderContextBuilder builder) { - super(builder); - } - - /** - * Get the deferred flag. Exchange rates can be deferred or real.time. - * - * @return the deferred flag, or {code null}. - */ - public Set getRateTypes() { - @SuppressWarnings("unchecked") - Set rateSet = get(KEY_RATE_TYPES, Set.class); - if (rateSet == null) { - return Collections.emptySet(); - } - return Collections.unmodifiableSet(rateSet); - } - - /** - * Creates a {@link ProviderContextBuilder} initialized with this instance's data. - * - * @return a new {@link ProviderContextBuilder}, never {@code null}. - */ - public ProviderContextBuilder toBuilder() { - return ProviderContextBuilder.create(this); - } - - /** - * Creates a new ProviderContext based on the provider id and rate type(s). - * - * @param provider the provider id, not null. - * @param rateType the required {@link RateType}, not null. - * @param rateTypes the required {@link RateType}s, not null - * @return a new {@link ProviderContext} instance. - */ - public static ProviderContext of(String provider, RateType rateType, RateType... rateTypes) { - return ProviderContextBuilder.of(provider, rateType, rateTypes).build(); - } - - /** - * Creates a new ProviderContext based on the provider id and rate type(s). - * - * @param provider the provider id, not null. - * @return a new {@link ProviderContext} instance. - */ - public static ProviderContext of(String provider) { - return ProviderContextBuilder.of(provider, RateType.ANY).build(); - } - -} diff --git a/src/main/java/javax/money/convert/ProviderContextBuilder.java b/src/main/java/javax/money/convert/ProviderContextBuilder.java deleted file mode 100644 index e6a1ae6a6..000000000 --- a/src/main/java/javax/money/convert/ProviderContextBuilder.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.AbstractContextBuilder; -import java.util.*; - -/** - * Builder class to of {@link ProviderContext} instances. Instances of - * this class are not thread-safe. - * - * @author Anatole Tresch - */ -public final class ProviderContextBuilder extends AbstractContextBuilder { - - /** - * Create a new Builder instance. - * - * @param provider the provider name, not {@code null}. - * @param rateTypes the rate types, not null and not empty. - */ - private ProviderContextBuilder(String provider, RateType rateType, RateType... rateTypes) { - Objects.requireNonNull(rateType, "At least one RateType is required."); - Objects.requireNonNull(rateTypes); - setProviderName(provider); - Set rts = new HashSet<>(); - rts.add(rateType); - Collections.addAll(rts, rateTypes); - set(ProviderContext.KEY_RATE_TYPES, rts); - } - - /** - * Create a new Builder instance. - * - * @param provider the provider name, not {@code null}. - * @param rateTypes the rate types, not null and not empty. - */ - private ProviderContextBuilder(String provider, Collection rateTypes) { - Objects.requireNonNull(rateTypes); - if (rateTypes.isEmpty()) { - throw new IllegalArgumentException("At least one RateType is required."); - } - setProviderName(provider); - Set rts = new HashSet<>(rateTypes); - set("rateTypes", rts); - } - - /** - * Create a new Builder, hereby using the given {@link ProviderContext} - * 's values as defaults. This allows changing an existing - * {@link ProviderContext} easily. - * - * @param context the context, not {@code null} - */ - private ProviderContextBuilder(ProviderContext context) { - importContext(context); - Set rts = new HashSet<>(context.getRateTypes()); - set(ProviderContext.KEY_RATE_TYPES, rts); - } - - /** - * Set the rate types. - * - * @param rateTypes the rate types, not null and not empty. - * @return this, for chaining. - * @throws IllegalArgumentException when not at least one {@link RateType} is provided. - */ - public ProviderContextBuilder setRateTypes(RateType... rateTypes) { - return setRateTypes(Arrays.asList(rateTypes)); - } - - /** - * Set the rate types. - * - * @param rateTypes the rate types, not null and not empty. - * @return this, for chaining. - * @throws IllegalArgumentException when not at least one {@link RateType} is provided. - */ - public ProviderContextBuilder setRateTypes(Collection rateTypes) { - Objects.requireNonNull(rateTypes); - if (rateTypes.isEmpty()) { - throw new IllegalArgumentException("At least one RateType is required."); - } - Set rtSet = new HashSet<>(rateTypes); - set(ProviderContext.KEY_RATE_TYPES, rtSet); - return this; - } - - /** - * Creates a new {@link ProviderContext} with the data from this Builder - * instance. - * - * @return a new {@link ProviderContext}. never {@code null}. - */ - public ProviderContext build() { - return new ProviderContext(this); - } - - /** - * Create a new ProviderContextBuilder, hereby using the given {@link ProviderContext} - * 's values as defaults. This allows changing an existing - * {@link ProviderContext} easily. - * - * @param context the context, not {@code null} - * @return a new {@link javax.money.convert.ProviderContextBuilder} instance, never null. - */ - public static ProviderContextBuilder create(ProviderContext context) { - return new ProviderContextBuilder(context); - } - - /** - * Create a new ProviderContextBuilder instance. - * - * @param provider the provider name, not {@code null}. - * @param rateType the required {@link RateType}, not null - * @param rateTypes the rate types, not null and not empty. - * @return a new {@link javax.money.convert.ProviderContextBuilder} instance, never null. - */ - public static ProviderContextBuilder of(String provider, RateType rateType, RateType... rateTypes) { - return new ProviderContextBuilder(provider, rateType, rateTypes); - } - - /** - * Create a new ProviderContextBuilder instance. - * - * @param provider the provider name, not {@code null}. - * @param rateTypes the rate types, not null and not empty. - * @return a new {@link javax.money.convert.ProviderContextBuilder} instance, never null. - */ - public static ProviderContextBuilder of(String provider, Collection rateTypes) { - return new ProviderContextBuilder(provider, rateTypes); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/convert/RateType.java b/src/main/java/javax/money/convert/RateType.java deleted file mode 100644 index 65d5b48e2..000000000 --- a/src/main/java/javax/money/convert/RateType.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -/** - * This enumeration defines the different type of rates that can be provided by {@link javax.money.convert - * .ExchangeRateProvider} implementations. Hereby the rate provider's {@link javax.money.convert.ProviderContext} can - * contain - * additional information about the rates provided. Similarly, when accessing {@link javax.money.convert - * .ExchangeRateProvider} or {@link javax.money.convert.CurrencyConversion} instances corresponding attributes can - * be passed within an (optional) {@link javax.money.convert.ConversionContext}. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public enum RateType{ - /** - * Historic rates, e.g. from the day before or older. - */ - HISTORIC, - /** - * Real-time rates should be as adequate as possible, basically not more than a few milliseconds late. - */ - REALTIME, - /** - * Deferred rates are basically also current rates, but have some fixed delay, e.g. 20 minutes. - */ - DEFERRED, - /** - * Any other type of rates. You may use the {@link javax.money.convert.ProviderContext}, - * {@link javax.money.convert.ConversionContext} to define additional details. - */ - OTHER, - /** - * Any type of rates. This can be used, where any type of rate is suitable. This may be feasible if you - * access a specific chain of rate providers, - * where the order of providers already implies a prioritization and the rate type in that scenario is not relevant. - */ - ANY -} \ No newline at end of file diff --git a/src/main/java/javax/money/convert/package-info.java b/src/main/java/javax/money/convert/package-info.java deleted file mode 100644 index 1803643cd..000000000 --- a/src/main/java/javax/money/convert/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Defines the monetary currency conversion API. - */ -package javax.money.convert; \ No newline at end of file diff --git a/src/main/java/javax/money/format/AmountFormatContext.java b/src/main/java/javax/money/format/AmountFormatContext.java deleted file mode 100644 index ca3759b3f..000000000 --- a/src/main/java/javax/money/format/AmountFormatContext.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import java.util.Locale; - -import javax.money.AbstractContext; -import javax.money.MonetaryAmountFactory; - - -/** - * The {@link AmountFormatContext} provides details about a {@link javax.money.format.MonetaryAmountFormat}. - * - * @author Anatole Tresch - * @see MonetaryAmountFormat#getContext() - */ -@SuppressWarnings("serial") -public final class AmountFormatContext extends AbstractContext { - /** - * Key used for the format name attribute. - */ - static final String KEY_FORMAT_NAME = "formatName"; - - /** - * Creates a new instance of {@link javax.money.format.AmountFormatContext}. - * - * @param builder the corresponding builder. - */ - AmountFormatContext(AmountFormatContextBuilder builder) { - super(builder); - } - - /** - * Access the style's {@link Locale}. - * - * @return the {@link Locale}, never {@code null}. - */ - public String getFormatName() { - return getText(KEY_FORMAT_NAME); - } - - /** - * Access the context's Locale. - * - * @return the Locale, or null. - */ - public Locale getLocale() { - return get(Locale.class); - } - - /** - * Access the format's {@link javax.money.MonetaryAmountFactory} that is used to of new amounts during - * parsing. If not set explicitly, the default {@link javax.money.MonetaryAmountFactory} is used. - * - * @return the {@link javax.money.MonetaryAmountFactory}, never {@code null}. - */ - public MonetaryAmountFactory getParseFactory() { - return get(MonetaryAmountFactory.class); - } - - /** - * Creates a new builder instances, initialized with the data from this one. - * - * @return a new {@link javax.money.format.AmountFormatContextBuilder} instance, never null. - */ - public AmountFormatContextBuilder toBuilder() { - return AmountFormatContextBuilder.of(this); - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/format/AmountFormatContextBuilder.java b/src/main/java/javax/money/format/AmountFormatContextBuilder.java deleted file mode 100644 index c20687228..000000000 --- a/src/main/java/javax/money/format/AmountFormatContextBuilder.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import javax.money.AbstractContextBuilder; -import javax.money.MonetaryAmountFactory; -import java.util.Locale; -import java.util.Objects; - -/** - * Builder class for creating new instances of {@link javax.money.format.AmountFormatContext} adding detailed - * information - * about a {@link javax.money.format.MonetaryAmountFormat} instance. - *

- * Note this class is NOT thread-safe. - * - * @see MonetaryAmountFormat#getContext() - */ -public final class AmountFormatContextBuilder - extends AbstractContextBuilder { - /** - * Map key used for the style identifier attribute. - */ - private static final String DEFAULT_FORMAT_NAME = "default"; - - /** - * Creates a new {@link AmountFormatContextBuilder}. - * - * @param formatQuery the base {@link AmountFormatQuery}, not {@code null}. - */ - private AmountFormatContextBuilder(AmountFormatQuery formatQuery) { - importContext(formatQuery); - } - - /** - * Creates a new {@link AmountFormatContextBuilder}. - * - * @param context the base {@link AmountFormatContext}, not {@code null}. - */ - private AmountFormatContextBuilder(AmountFormatContext context) { - Objects.requireNonNull(context); - importContext(context); - } - - /** - * Creates a new {@link AmountFormatContextBuilder}. - * - * @param formatName the target formatName {@link String}, not {@code null}. - */ - private AmountFormatContextBuilder(String formatName) { - Objects.requireNonNull(formatName, "formatName required."); - set(AmountFormatContext.KEY_FORMAT_NAME, formatName); - } - - /** - * Creates a new default {@link AmountFormatContextBuilder} for a formatter based on the locale specific - * defaults. - * - * @param locale the target {@link java.util.Locale}, not {@code null}. - */ - private AmountFormatContextBuilder(Locale locale) { - Objects.requireNonNull(locale, "locale required."); - setLocale(locale); - set(AmountFormatContext.KEY_FORMAT_NAME, DEFAULT_FORMAT_NAME); - } - - /** - * Sets a format's name. - * - * @param formatName the formatName, not null. - * @return the Builder, for chaining. - */ - public AmountFormatContextBuilder setFormatName(String formatName) { - return set(AmountFormatContext.KEY_FORMAT_NAME, formatName); - } - - /** - * Sets a Locale to be applied. - * - * @param locale the locale, not null. - * @return the Builder, for chaining. - */ - public AmountFormatContextBuilder setLocale(Locale locale) { - return set(locale); - } - - /** - * Sets the {@link javax.money.MonetaryContext} to be used, when amount's are parsed. - * - * @param monetaryAmountBuilder the monetary amount factory, not {@code null}. - * @return this builder for chaining. - */ - public AmountFormatContextBuilder setMonetaryAmountFactory( - @SuppressWarnings("rawtypes") MonetaryAmountFactory monetaryAmountBuilder) { - Objects.requireNonNull(monetaryAmountBuilder); - return set(MonetaryAmountFactory.class, monetaryAmountBuilder); - } - - /** - * Creates a new instance of {@link AmountFormatContext} that configures a {@link javax.money.format - * .MonetaryAmountFormat}. - * - * @return a new {@link AmountFormatContext} instance. - */ - @Override - public AmountFormatContext build() { - return new AmountFormatContext(this); - } - - /** - * Creates a new {@link AmountFormatContextBuilder}. - * - * @param formatQuery the base {@link AmountFormatContext}, not {@code null}. - * @return a new {@link javax.money.format.AmountFormatContextBuilder} instance, never null. - */ - public static AmountFormatContextBuilder create(AmountFormatQuery formatQuery) { - return new AmountFormatContextBuilder(formatQuery); - } - - /** - * Creates a new {@link AmountFormatContextBuilder}. - * - * @param context the {@link AmountFormatContext} - * @return a new {@link javax.money.format.AmountFormatContextBuilder} instance, never null. - */ - public static AmountFormatContextBuilder of(AmountFormatContext context) { - return new AmountFormatContextBuilder(context); - } - - /** - * Creates a new {@link AmountFormatContextBuilder}. - * - * @param formatName the target formatName {@link String}, not {@code null}. - * @return a new {@link javax.money.format.AmountFormatContextBuilder} instance, never null. - */ - public static AmountFormatContextBuilder of(String formatName) { - return new AmountFormatContextBuilder(formatName); - } - - /** - * Creates a new default {@link AmountFormatContextBuilder} for a formatter based on the locale specific - * defaults. - * - * @param locale the target {@link java.util.Locale}, not {@code null}. - * @return a new {@link javax.money.format.AmountFormatContextBuilder} instance, never null. - */ - public static AmountFormatContextBuilder of(Locale locale) { - return new AmountFormatContextBuilder(locale); - } -} \ No newline at end of file diff --git a/src/main/java/javax/money/format/AmountFormatQuery.java b/src/main/java/javax/money/format/AmountFormatQuery.java deleted file mode 100644 index d9914624f..000000000 --- a/src/main/java/javax/money/format/AmountFormatQuery.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import java.util.Locale; - -import javax.money.AbstractQuery; -import javax.money.Monetary; -import javax.money.MonetaryAmountFactory; - -/** - * Query for accessing instances of {@link javax.money.format.MonetaryAmountFormat}. In general it is determined by the - * implementation, what formats are provided. Nevertheless the following queries must be supported: - *

    - *
  • Accessing a format based on a Locale, that is also supported by {@link java.text - * .DecimalFormat#getAvailableLocales()}.
  • - *
- * All other formats are optional. For further details about supported formats refer to the implementation's - * documentation. - *

- * This class is immutable, thread-safe and serializable. - */ -public final class AmountFormatQuery extends AbstractQuery { - - - private static final long serialVersionUID = 5848832058616502383L; - /** - * Key used for the format name attribute. - */ - static final String KEY_QUERY_FORMAT_NAME = "Query.formatName"; - - /** - * Constructor, used from the Builder. - * - * @param builder the corresponding {@link javax.money.format.AmountFormatQueryBuilder}, not null. - */ - AmountFormatQuery(AmountFormatQueryBuilder builder) { - super(builder); - } - - /** - * Gets a style's id. - * - * @return the styleId, or null. - */ - public String getFormatName() { - return getText(KEY_QUERY_FORMAT_NAME); - } - - /** - * Gets a Locale to be applied. - * - * @return the style's locale, or null. - */ - public Locale getLocale() { - return get(Locale.class); - } - - /** - * Gets the {@link javax.money.MonetaryAmountFactoryQuery} to be used for accessing {@link javax.money - * .MonetaryAmountFactory}, when amount's are parsed. - * - * @return the monetary context, or {@code null}. - */ - @SuppressWarnings("rawtypes") - public MonetaryAmountFactory getMonetaryAmountFactory() { - MonetaryAmountFactory factory = get(MonetaryAmountFactory.class); - if (factory == null) { - return Monetary.getDefaultAmountFactory(); - } - return factory; - } - - /** - * Creates a simple format query based on a single Locale, similar to {@link java.text.DecimalFormat#getInstance - * (java.util.Locale)}. - * - * @param locale the target locale, not null. - * @param providers the providers to be used, not null. - * @return a new query instance - */ - public static AmountFormatQuery of(Locale locale, String... providers) { - return AmountFormatQueryBuilder.of(locale).setProviderNames(providers).build(); - } - - /** - * Get a {@link javax.money.format.AmountFormatQueryBuilder} preinitialized with this context instance. - * - * @return a new preinitialized builder, never null. - */ - public AmountFormatQueryBuilder toBuilder() { - return AmountFormatQueryBuilder.of(this); - } -} diff --git a/src/main/java/javax/money/format/AmountFormatQueryBuilder.java b/src/main/java/javax/money/format/AmountFormatQueryBuilder.java deleted file mode 100644 index 9e971cfab..000000000 --- a/src/main/java/javax/money/format/AmountFormatQueryBuilder.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import javax.money.AbstractQueryBuilder; -import javax.money.MonetaryAmountFactory; -import javax.money.MonetaryAmountFactoryQuery; -import java.util.Locale; -import java.util.Objects; - -/** - * Builder for queries for accessing/configuring {@link javax.money.format.MonetaryAmountFormat} instances. - *

- * Note this class is NOT thread-safe. - */ -public final class AmountFormatQueryBuilder extends AbstractQueryBuilder { - /** - * The default format name used. - */ - private static final String DEFAULT_FORMAT_NAME = "default"; - - /** - * Creates a new {@link AmountFormatQueryBuilder}. - * - * @param formatQuery the base {@link AmountFormatQuery}, not {@code null}. - */ - private AmountFormatQueryBuilder(AmountFormatQuery formatQuery) { - importContext(formatQuery); - } - - /** - * Creates a new {@link AmountFormatQueryBuilder}. - * - * @param formatName the target format's name {@link String}, not {@code null}. - */ - private AmountFormatQueryBuilder(String formatName) { - Objects.requireNonNull(formatName, "formatName required."); - set(AmountFormatQuery.KEY_QUERY_FORMAT_NAME, formatName); - } - - /** - * Creates a new default {@link AmountFormatQueryBuilder} for a formatter based on the - * locale specific - * defaults. - * - * @param locale the target {@link java.util.Locale}, not {@code null}. - */ - private AmountFormatQueryBuilder(Locale locale) { - Objects.requireNonNull(locale, "locale required."); - setLocale(locale); - set(AmountFormatQuery.KEY_QUERY_FORMAT_NAME, DEFAULT_FORMAT_NAME); - } - - /** - * Sets a style's id. - * - * @param formatName the format's name, not null. - * @return the Builder, for chaining. - */ - public AmountFormatQueryBuilder setFormatName(String formatName) { - return set(AmountFormatQuery.KEY_QUERY_FORMAT_NAME, formatName); - } - - /** - * Sets a Locale to be applied. - * - * @param locale the locale, not null. - * @return the Builder, for chaining. - */ - public AmountFormatQueryBuilder setLocale(Locale locale) { - return set(locale); - } - - /** - * Sets the {@link javax.money.MonetaryContext} to be used, when amount's are parsed. - * - * @param monetaryQuery the monetary query, not {@code null}. - * @return this builder for chaining. - */ - public AmountFormatQueryBuilder setMonetaryQuery(MonetaryAmountFactoryQuery monetaryQuery) { - Objects.requireNonNull(monetaryQuery); - return set(monetaryQuery); - } - - /** - * Sets the {@link javax.money.MonetaryAmountFactory} to be used to of amounts during parsing. - * - * @param monetaryFactory the {@link javax.money.MonetaryAmountFactory} to be used, not null. - * @return this builder for chaining. - */ - public AmountFormatQueryBuilder setMonetaryAmountFactory(MonetaryAmountFactory monetaryFactory) { - Objects.requireNonNull(monetaryFactory); - return set(MonetaryAmountFactory.class, monetaryFactory); - } - - /** - * Creates a new {@link javax.money.format.AmountFormatQuery} instance. - * - * @return a new {@link javax.money.format.AmountFormatQuery} instance, never null. - */ - public AmountFormatQuery build() { - return new AmountFormatQuery(this); - } - - /** - * Creates a new {@link AmountFormatQueryBuilder} and initializes it with the values from {@code formatQuery}. - * - * @param formatQuery the base {@link AmountFormatContext}, not {@code null}. - * @return a new {@link javax.money.format.AmountFormatQueryBuilder} instance, never null. - */ - public static AmountFormatQueryBuilder of(AmountFormatQuery formatQuery) { - return new AmountFormatQueryBuilder(formatQuery); - } - - /** - * Creates a new {@link AmountFormatQueryBuilder}. - * - * @param formatName the target format's name {@link String}, not {@code null}. - * @return a new {@link javax.money.format.AmountFormatQueryBuilder} instance, never null. - */ - public static AmountFormatQueryBuilder of(String formatName) { - return new AmountFormatQueryBuilder(formatName); - } - - /** - * Creates a new default {@link AmountFormatQueryBuilder} for a formatter based on the - * locale specific - * defaults. - * - * @param locale the target {@link java.util.Locale}, not {@code null}. - * @return a new {@link javax.money.format.AmountFormatQueryBuilder} instance, never null. - */ - public static AmountFormatQueryBuilder of(Locale locale) { - return new AmountFormatQueryBuilder(locale); - } - - -} diff --git a/src/main/java/javax/money/format/MonetaryAmountFormat.java b/src/main/java/javax/money/format/MonetaryAmountFormat.java deleted file mode 100644 index 59583cdfe..000000000 --- a/src/main/java/javax/money/format/MonetaryAmountFormat.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import javax.money.MonetaryAmount; -import javax.money.MonetaryContext; -import javax.money.MonetaryQuery; -import java.io.IOException; - -/** - *

- * Formats instances of {@code MonetaryAmount} to a {@link String} or an {@link Appendable}. - *

- *

- * To obtain a MonetaryAmountFormat for a specific locale, including the default - * locale, call {@link MonetaryFormats#getAmountFormat(java.util.Locale, String...)}. - * - * More complex formatting scenarios can be implemented by registering instances of {@link javax.money.spi - * .MonetaryAmountFormatProviderSpi}. - * The spi implementation creates new instances of {@link javax.money.format.MonetaryAmountFormat} based on the - * styleId and (arbitrary) attributes passed within the {@link javax.money.format.AmountFormatContext}. - *

- *

In general, do prefer - * accessing MonetaryAmountFormat instances from the {@link MonetaryFormats} singleton, - * instead of instantiating implementations directly, since the MonetaryFormats factory - * method may return different subclasses or may implement contextual behaviour (in a EE context). - * If you need to customize the format object, do something like this: - *

- *
- *

- * MonetaryAmountFormat f = MonetaryFormats.getInstance(loc);
- * f.setStyle(f.getStyle().toBuilder().setPattern("###.##;(###.##)").build());
- * 
- *
- *

Special Values

- * - *

- * Negative zero ("-0") should always parse to - *

    - *
  • 0
  • - *
- * - *

Synchronization

- * - *

- * Instances of this class are not required to be thread-safe. It is recommended to of separate - * format instances for each thread. If multiple threads access a format concurrently, it must be - * synchronized externally. - * - *

Example

- *
- *

- * // Print out a number using the localized number, currency,
- * // for each locale
- * Locale[] locales = MonetaryFormats.getAvailableLocales();
- * MonetaryAmount amount = ...;
- * MonetaryAmountFormat form;
- *     System.out.println("FORMAT");
- *     for (int i = 0; i < locales.length; ++i) {
- *         if (locales[i].getCountry().length() == 0) {
- *            continue; // Skip language-only locales
- *         }
- *         System.out.print(locales[i].getDisplayName());
- *         form = MonetaryFormats.getInstance(locales[i]);
- *         System.out.print(": " + form.getStyle().getPattern());
- *         String myAmount = form.format(amount);
- *         System.out.print(" -> " + myAmount);
- *         try {
- *             System.out.println(" -> " + form.parse(form.format(myAmount)));
- *         } catch (ParseException e) {}
- *     }
- * }
- * 
- *
- */ -public interface MonetaryAmountFormat extends MonetaryQuery{ - - - /** - * The {@link AmountFormatContext} to be applied when a {@link MonetaryAmount} is formatted. - * - * @return the {@link AmountFormatContext} used, never {@code null}. - */ - AmountFormatContext getContext(); - - - /** - * Formats the given {@link MonetaryAmount} to a String. - * - * @param amount the amount to format, not {@code null} - * @return the string printed using the settings of this formatter - * @throws UnsupportedOperationException if the formatter is unable to print - * @throws IllegalStateException if an IO error occurs. - */ - default String format(MonetaryAmount amount){ - StringBuilder b = new StringBuilder(); - try{ - print(b, amount); - } - catch(IOException e){ - throw new IllegalStateException("Formatting error.", e); - } - return b.toString(); - } - - /** - * Formats the given {@link MonetaryAmount} to a {@code Appendable}. - *

- * Example implementations of {@code Appendable} are {@code StringBuilder}, {@code StringBuffer} - * or {@code Writer}. Note that {@code StringBuilder} and {@code StringBuffer} never throw an - * {@code IOException}. - * - * @param appendable the appendable to add to, not null - * @param amount the amount to print, not null - * @throws UnsupportedOperationException if the formatter is unable to print - * @throws IOException if an IO error occurs, thrown by the {@code appendable} - * @throws MonetaryParseException if there is a problem while parsing - */ - void print(Appendable appendable, MonetaryAmount amount) throws IOException; - - /** - * Fully parses the text into an instance of {@link MonetaryAmount}. - *

- * The parse must complete normally and parse the entire text. If the parse completes without - * reading the entire length of the text, an exception is thrown. If any other problem occurs - * during parsing, an exception is thrown. - *

- * Additionally the effective implementation type returned can be determined by the - * {@link MonetaryContext} applied to the {@link MonetaryAmountFormat}. This formatter will call - * {@link javax.money.Monetary#getDefaultAmountType()} and will use the result returned - * to access a corresponding {@link javax.money.MonetaryAmountFactory} to of the instance - * returned. - * - * @param text the text to parse, not null - * @return the parsed value, never {@code null} - * @throws UnsupportedOperationException if the formatter is unable to parse - * @throws MonetaryParseException if there is a problem while parsing - */ - MonetaryAmount parse(CharSequence text) throws MonetaryParseException; - -} diff --git a/src/main/java/javax/money/format/MonetaryFormats.java b/src/main/java/javax/money/format/MonetaryFormats.java deleted file mode 100644 index 7903d24bd..000000000 --- a/src/main/java/javax/money/format/MonetaryFormats.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import javax.money.MonetaryException; -import javax.money.spi.Bootstrap; -import javax.money.spi.MonetaryAmountFormatProviderSpi; -import javax.money.spi.MonetaryFormatsSingletonSpi; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * This class models the singleton accessor for {@link MonetaryAmountFormat} instances. - *

- * This class is thread-safe. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public final class MonetaryFormats { - - private static MonetaryFormatsSingletonSpi getMonetaryFormatsSpi() { - return loadMonetaryFormatsSingletonSpi(); - } - - /** - * Private singleton constructor. - */ - private MonetaryFormats() { - // Singleton - } - - /** - * Loads the SPI backing bean. - * - * @return the instance of MonetaryFormatsSingletonSpi to be used by this singleton. - */ - private static MonetaryFormatsSingletonSpi loadMonetaryFormatsSingletonSpi() { - try { - return Optional.ofNullable(Bootstrap.getService(MonetaryFormatsSingletonSpi.class)) - .orElseGet(DefaultMonetaryFormatsSingletonSpi::new); - } catch (Exception e) { - Logger.getLogger(MonetaryFormats.class.getName()) - .log(Level.WARNING, "Failed to load MonetaryFormatsSingletonSpi, using default.", e); - return new DefaultMonetaryFormatsSingletonSpi(); - } - } - - /** - * Checks if a {@link MonetaryAmountFormat} is available for the given {@link Locale} and providers. - * - * @param locale the target {@link Locale}, not {@code null}. - * @param providers The providers to be queried, if not set the providers as defined by #getDefaultCurrencyProviderChain() - * are queried. - * @return true, if a corresponding {@link MonetaryAmountFormat} is accessible. - */ - public static boolean isAvailable(Locale locale, String... providers) { - return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( - "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) - .isAvailable(locale, providers); - } - - /** - * Access the default {@link MonetaryAmountFormat} given a {@link Locale}. - * - * @param locale the target {@link Locale}, not {@code null}. - * @param providers The providers to be queried, if not set the providers as defined by #getDefaultCurrencyProviderChain() - * are queried. - * @return the matching {@link MonetaryAmountFormat} - * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a - * corresponding {@link MonetaryAmountFormat} instance. - */ - public static MonetaryAmountFormat getAmountFormat(Locale locale, String... providers) { - return getAmountFormat(AmountFormatQueryBuilder.of(locale).setProviderNames(providers).setLocale(locale).build()); - } - - /** - * Checks if a {@link MonetaryAmountFormat} is available for the given {@link javax.money.format.AmountFormatQuery}. - * - * @param formatQuery the required {@link AmountFormatQuery}, not {@code null}. If the query does not define - * any explicit provider chain, the providers as defined by #getDefaultCurrencyProviderChain() - * are used. - * @return true, if a corresponding {@link MonetaryAmountFormat} is accessible. - */ - public static boolean isAvailable(AmountFormatQuery formatQuery) { - return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( - "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) - .isAvailable(formatQuery); - } - - /** - * Access the default {@link MonetaryAmountFormat} given a {@link Locale}. - * - * @param formatQuery the required {@link AmountFormatQuery}, not {@code null}. If the query does not define - * any explicit provider chain, the providers as defined by #getDefaultCurrencyProviderChain() - * are used. - * @return the matching {@link MonetaryAmountFormat} - * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a - * corresponding {@link MonetaryAmountFormat} instance. - */ - public static MonetaryAmountFormat getAmountFormat(AmountFormatQuery formatQuery) { - return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( - "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) - .getAmountFormat(formatQuery); - } - - /** - * Access all {@link MonetaryAmountFormat} instances that match the given a {@link AmountFormatQuery}. - * - * @param formatQuery the required {@link AmountFormatQuery}, not {@code null}. If the query does not define - * any explicit provider chain, the providers as defined by #getDefaultCurrencyProviderChain() - * are used. - * @return the matching {@link MonetaryAmountFormat} - * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a - * corresponding {@link MonetaryAmountFormat} instance. - */ - public static Collection getAmountFormats(AmountFormatQuery formatQuery) { - return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( - "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) - .getAmountFormats(formatQuery); - } - - /** - * Access the a {@link MonetaryAmountFormat} given its styleId. - * - * @param formatName the target format name, not {@code null}. - * @param providers The providers to be used, if not set the providers as defined by #getDefaultCurrencyProviderChain() are - * used. - * @return the matching {@link MonetaryAmountFormat} - * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a - * corresponding {@link MonetaryAmountFormat} instance. - */ - public static MonetaryAmountFormat getAmountFormat(String formatName, String... providers) { - return getAmountFormat(AmountFormatQueryBuilder.of(formatName).setProviderNames(providers).build()); - } - - /** - * Get all available locales. This equals to {@link MonetaryAmountFormatProviderSpi#getAvailableLocales()}. - * - * @param providers The providers to be used, if not set the providers as defined by #getDefaultCurrencyProviderChain() are - * used. - * @return all available locales, never {@code null}. - */ - public static Set getAvailableLocales(String... providers) { - return getMonetaryFormatsSpi().getAvailableLocales(providers); - } - - /** - * Get the names of the currently registered format providers. - * - * @return the provider names, never null. - */ - public static Collection getFormatProviderNames() { - Collection providers = Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow( - () -> new MonetaryException( - "No MonetaryFormatsSingletonSpi loaded, query functionality is not available.")) - .getProviderNames(); - if (Objects.isNull(providers)) { - Logger.getLogger(MonetaryFormats.class.getName()).warning( - "No supported rate/conversion providers returned by SPI: " + - getMonetaryFormatsSpi().getClass().getName()); - return Collections.emptySet(); - } - return providers; - } - - /** - * Get the default provider chain, identified by the unique provider names in order as evaluated and used. - * - * @return the default provider chain, never null. - */ - public static List getDefaultFormatProviderChain() { - return Optional.ofNullable(getMonetaryFormatsSpi()).orElseThrow(() -> new MonetaryException( - "No MonetaryFormatsSingletonSpi " + "loaded, query functionality is not available.")) - .getDefaultProviderChain(); - } - - /** - * This class models the singleton accessor for {@link javax.money.format.MonetaryAmountFormat} instances. - *

- * This class is thread-safe. - * - * @author Anatole Tresch - * @author Werner Keil - */ - public static final class DefaultMonetaryFormatsSingletonSpi implements MonetaryFormatsSingletonSpi { - - - /** - * Access an {@link javax.money.format.MonetaryAmountFormat} given a {@link javax.money.format - * .AmountFormatContext}. - * - * @param formatQuery The format query defining the requirements of the formatter. - * @return the corresponding {@link javax.money.format.MonetaryAmountFormat} - * @throws javax.money.MonetaryException if no registered {@link javax.money.spi - * .MonetaryAmountFormatProviderSpi} can provide a - * corresponding {@link javax.money.format.MonetaryAmountFormat} instance. - */ - @Override - public Collection getAmountFormats(AmountFormatQuery formatQuery) { - Collection result = new ArrayList<>(); - for (MonetaryAmountFormatProviderSpi spi : Bootstrap.getServices(MonetaryAmountFormatProviderSpi.class)) { - Collection formats = spi.getAmountFormats(formatQuery); - if (Objects.nonNull(formats)) { - result.addAll(formats); - } - } - return result; - } - - @Override - public Set getProviderNames() { - return getSpisAsMap().keySet(); - } - - /** - * This default implementation simply returns all providers defined in arbitrary order. - * - * @return the default provider chain, never null. - */ - @Override - public List getDefaultProviderChain() { - List list = new ArrayList<>(getProviderNames()); - Collections.sort(list); - return list; - } - - - /** - * Get all available locales. This equals to {@link javax.money.spi - * .MonetaryAmountFormatProviderSpi#getAvailableLocales()}. - * - * @return all available locales, never {@code null}. - */ - @Override - public Set getAvailableLocales(String... providerNames) { - Set locales = new HashSet<>(); - Collection spis = getSpis(providerNames); - for (MonetaryAmountFormatProviderSpi spi : spis) { - locales.addAll(spi.getAvailableLocales()); - } - return locales; - } - - private Map getSpisAsMap() { - Map spis = new ConcurrentHashMap<>(); - for (MonetaryAmountFormatProviderSpi spi : Bootstrap.getServices(MonetaryAmountFormatProviderSpi.class)) { - if (spi.getProviderName() == null) { - Logger.getLogger(MonetaryFormats.class.getName()).warning("MonetaryAmountFormatProviderSpi " + - "returns null for " + - "getProviderName: " + - spi.getClass().getName()); - } - spis.put(spi.getProviderName(), spi); - } - return spis; - } - - private Collection getSpis(String... providerNames) { - List providers = new ArrayList<>(); - Map spis = getSpisAsMap(); - if (providerNames.length == 0) { - providers.addAll(spis.values()); - } else { - for (String provName : providerNames) { - MonetaryAmountFormatProviderSpi spi = spis.get(provName); - if (Objects.isNull(spi)) { - throw new IllegalArgumentException("MonetaryAmountFormatProviderSpi not found: " + provName); - } - providers.add(spi); - } - } - return providers; - } - - } -} diff --git a/src/main/java/javax/money/format/MonetaryParseException.java b/src/main/java/javax/money/format/MonetaryParseException.java deleted file mode 100644 index 5e6fc74bd..000000000 --- a/src/main/java/javax/money/format/MonetaryParseException.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import java.util.Objects; - -import javax.money.MonetaryException; - -/** - * Signals that an error has been reached unexpectedly while parsing. - * - * @author Werner Keil - */ -public class MonetaryParseException extends MonetaryException { - - /** - * serialVersionUID. - */ - private static final long serialVersionUID = -2855079387296896628L; - - /** - * The zero-based character offset into the string being parsed at which the - * error was found during parsing. - * - * @serial - */ - private int errorIndex; - - /** The original input data. */ - private CharSequence data; - - /** - * Constructs a MonetaryParseException with the specified detail message, - * parsed text and index. A detail message is a String that describes this - * particular exception. - * - * @param message - * the detail message - * @param parsedData - * the parsed text, should not be null - * @param errorIndex - * the position where the error is found while parsing. - */ - public MonetaryParseException(String message, CharSequence parsedData, - int errorIndex) { - super(message); - if(errorIndex > parsedData.length()){ - throw new IllegalArgumentException("Invalid error index > input.length"); - } - this.data = parsedData; - this.errorIndex = errorIndex; - } - - /** - * Constructs a MonetaryParseException with the parsed text and offset. A - * detail message is a String that describes this particular exception. - * - * @param parsedData - * the parsed text, should not be null - * @param errorIndex - * the position where the error is found while parsing. - */ - public MonetaryParseException(CharSequence parsedData, - int errorIndex) { - super("Parse Error"); - if(errorIndex > parsedData.length()){ - throw new IllegalArgumentException("Invalid error index > input.length"); - } - this.data = parsedData; - this.errorIndex = errorIndex; - } - - /** - * Returns the index where the error was found. - * - * @return the index where the error was found - */ - public int getErrorIndex() { - return errorIndex; - } - - /** - * Returns the string that was being parsed. - * - * @return the parsed input string, or {@code null}, if {@code null} was passed as - * input. - */ - public String getInput() { - - if (Objects.isNull(data)) { - return null; - } - return data.toString(); - } - -} diff --git a/src/main/java/javax/money/format/package-info.java b/src/main/java/javax/money/format/package-info.java deleted file mode 100644 index 5f1512f22..000000000 --- a/src/main/java/javax/money/format/package-info.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Money and Currency format API. In more detail: - *

    - *
  • JSR 354 defines a minimal {@link javax.money.format.MonetaryAmountFormat} that adopts - * existing formatting functionality, such as in javax.text.DecimalFormat.
  • - *
  • Some of the functionality from javax.text.DecimalFormat are remodeled, to be - * platform independent. Nevertheless the reference implementation may be built on top of existing JDK - * functionality.
  • - *
  • Additionally it adds customizable grouping sizes and characters as well as additional - * (extensible) currency formatting capabilities.
  • - *
- */ -package javax.money.format; - diff --git a/src/main/java/javax/money/package-info.java b/src/main/java/javax/money/package-info.java deleted file mode 100644 index fb9cc930d..000000000 --- a/src/main/java/javax/money/package-info.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Main package of the Money and Currency API. In more detail: - *
    - *
  • JSR 354 defines a minimal set of interfaces for interoperability, since - * concrete usage scenarios do not allow to define an implementation that is - * capable of covering all aspects identified. Consequently it must be possible - * that implementations can provide several implementations for monetary - * amounts. - * - * Users should not reference the interfaces, instead the value types should be - * used.
  • - *
  • Implementations must provide value types for currencies and amounts, - * implementing {@link javax.money.CurrencyUnit} and - * {@link javax.money.MonetaryAmount}.
  • - *
  • Implementations must also provide a minimal set of roundings, modeled as - * {@link javax.money.MonetaryRounding}. This should include basic roundings for - * ISO currencies, roundings defined by {@link java.math.MathContext} or - * {@link java.math.RoundingMode}.
  • - *
  • This API must avoid restrictions that prevents its use in different - * runtime environments, such as EE or ME.
  • - *
  • Method naming and style for currency modeling should be in alignment - * with parts of the Java Collection API or {@code java.time} / [JodaMoney].
  • - *
- */ -package javax.money; - diff --git a/src/main/java/javax/money/spi/Bootstrap.java b/src/main/java/javax/money/spi/Bootstrap.java deleted file mode 100644 index 460032717..000000000 --- a/src/main/java/javax/money/spi/Bootstrap.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import java.util.*; -import java.util.logging.Logger; - -/** - * This singleton provides access to the services available in the current runtime environment and context. The - * behaviour can be adapted, by calling {@link Bootstrap#init(ServiceProvider)} before accessing any monetary - * services. - * - * @author Anatole Tresch - */ -public final class Bootstrap { - /** - * The ServiceProvider used. - */ - private static volatile ServiceProvider serviceProviderDelegate; - /** - * The shared lock instance user. - */ - private static final Object LOCK = new Object(); - - /** - * Private singletons constructor. - */ - private Bootstrap() { - } - - /** - * Load the {@link ServiceProvider} to be used. - * - * @return {@link ServiceProvider} to be used for loading the services. - */ - private static ServiceProvider loadDefaultServiceProvider() { - try { - //noinspection LoopStatementThatDoesntLoop - for (ServiceProvider sp : ServiceLoader.load(ServiceProvider.class)) { - return sp; - } - } catch (Exception e) { - Logger.getLogger(Bootstrap.class.getName()).info("No ServiceProvider loaded, using default."); - } - return new DefaultServiceProvider(); - } - - /** - * Replace the current {@link ServiceProvider} in use. - * - * @param serviceProvider the new {@link ServiceProvider} - * @return the removed , or null. - */ - public static ServiceProvider init(ServiceProvider serviceProvider) { - Objects.requireNonNull(serviceProvider); - synchronized (LOCK) { - if (Objects.isNull(Bootstrap.serviceProviderDelegate)) { - Bootstrap.serviceProviderDelegate = serviceProvider; - Logger.getLogger(Bootstrap.class.getName()) - .info("Money Bootstrap: new ServiceProvider set: " + serviceProvider.getClass().getName()); - return null; - } else { - ServiceProvider prevProvider = Bootstrap.serviceProviderDelegate; - Bootstrap.serviceProviderDelegate = serviceProvider; - Logger.getLogger(Bootstrap.class.getName()) - .warning("Money Bootstrap: ServiceProvider replaced: " + serviceProvider.getClass().getName()); - return prevProvider; - } - } - } - - /** - * Ge {@link ServiceProvider}. If necessary the {@link ServiceProvider} will be lazily loaded. - * - * @return the {@link ServiceProvider} used. - */ - static ServiceProvider getServiceProvider() { - if (Objects.isNull(serviceProviderDelegate)) { - synchronized (LOCK) { - if (Objects.isNull(serviceProviderDelegate)) { - serviceProviderDelegate = loadDefaultServiceProvider(); - } - } - } - return serviceProviderDelegate; - } - - /** - * Delegate method for {@link ServiceProvider#getServices(Class)}. - * - * @param serviceType the service type. - * @return the services found. - * @see ServiceProvider#getServices(Class) - */ - public static Collection getServices(Class serviceType) { - return getServiceProvider().getServices(serviceType); - } - - /** - * Delegate method for {@link ServiceProvider#getServices(Class)}. - * - * @param serviceType the service type. - * @return the service found, or {@code null}. - * @see ServiceProvider#getServices(Class) - */ - public static T getService(Class serviceType) { - List services = getServiceProvider().getServices(serviceType); - return services - .stream() - .findFirst() - .orElse(null); - } - -} diff --git a/src/main/java/javax/money/spi/CurrencyProviderSpi.java b/src/main/java/javax/money/spi/CurrencyProviderSpi.java deleted file mode 100644 index db1d7e66a..000000000 --- a/src/main/java/javax/money/spi/CurrencyProviderSpi.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import javax.money.CurrencyQuery; -import javax.money.CurrencyUnit; -import java.util.Set; - -/** - * SPI (core) to be registered using the {@link javax.money.spi.Bootstrap}, which allows to - * register/provide additional currencies into the system automatically on - * startup. The implementation is allowed to be implemented in y contextual way, - * so depending on the runtime context, different currencies may be available. - * - * @author Anatole Tresch - */ -public interface CurrencyProviderSpi{ - - - /** - * The unique name of this currency provider instance. - * @return the unique provider id, never null or empty. - */ - default String getProviderName(){ - return getClass().getSimpleName(); - } - - /** - * Checks if a {@link CurrencyUnit} instances matching the given - * {@link javax.money.CurrencyContext} is available from this provider. - * - * @param query the {@link javax.money.CurrencyQuery} containing the parameters determining the query. not null. - * @return false, if no such unit is provided by this provider. - */ - default boolean isCurrencyAvailable(CurrencyQuery query){ - return !getCurrencies(query).isEmpty(); - } - - /** - * Return a {@link CurrencyUnit} instances matching the given - * {@link javax.money.CurrencyContext}. - * - * @param query the {@link javax.money.CurrencyQuery} containing the parameters determining the query. not null. - * @return the corresponding {@link CurrencyUnit}s matching, never null. - */ - Set getCurrencies(CurrencyQuery query); - -} diff --git a/src/main/java/javax/money/spi/DefaultServiceProvider.java b/src/main/java/javax/money/spi/DefaultServiceProvider.java deleted file mode 100644 index 69bd4f1bf..000000000 --- a/src/main/java/javax/money/spi/DefaultServiceProvider.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * This class implements the (default) {@link ServiceProvider} interface and hereby uses the JDK - * {@link ServiceLoader} to load the services required. - * - * @author Anatole Tresch - */ -class DefaultServiceProvider implements ServiceProvider { - /** List of services loaded, per class. */ - private final ConcurrentHashMap, List> servicesLoaded = new ConcurrentHashMap<>(); - - @Override - public int getPriority() { - return 0; - } - - /** - * Loads and registers services. - * - * @param serviceType - * The service type. - * @param - * the concrete type. - * @return the items found, never {@code null}. - */ - @Override - public List getServices(final Class serviceType) { - @SuppressWarnings("unchecked") - List found = (List) servicesLoaded.get(serviceType); - if (found != null) { - return found; - } - - return loadServices(serviceType); - } - - /** - * Loads and registers services. - * - * @param serviceType The service type. - * @param the concrete type. - * - * @return the items found, never {@code null}. - */ - private List loadServices(final Class serviceType) { - List services = new ArrayList<>(); - try { - for (T t : ServiceLoader.load(serviceType)) { - services.add(t); - } - services.sort(Comparator.comparing(o -> o.getClass().getSimpleName())); - @SuppressWarnings("unchecked") - final List previousServices = (List) servicesLoaded.putIfAbsent(serviceType, (List) services); - return Collections.unmodifiableList(previousServices != null ? previousServices : services); - } catch (Exception e) { - Logger.getLogger(DefaultServiceProvider.class.getName()).log(Level.WARNING, - "Error loading services of type " + serviceType, e); - return services; - } - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/spi/MonetaryAmountFactoryProviderSpi.java b/src/main/java/javax/money/spi/MonetaryAmountFactoryProviderSpi.java deleted file mode 100644 index 244a61f9b..000000000 --- a/src/main/java/javax/money/spi/MonetaryAmountFactoryProviderSpi.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import javax.money.MonetaryAmount; -import javax.money.MonetaryAmountFactory; -import javax.money.MonetaryContext; - -/** - * SPI (core): Implementations of this interface are used by the {@link MonetaryAmountsSingletonSpi} to evaluate the - * correct {@link javax.money.MonetaryAmountFactory} instances. - * - * @param the concrete amount type. - * @author Anatole Tresch - */ -public interface MonetaryAmountFactoryProviderSpi{ - - /** - * Determines how the factory should be considered when querying for matching implementation - * types calling {@link javax.money.Monetary#getAmountFactory(javax.money.MonetaryAmountFactoryQuery)} . - * - * @see javax.money.Monetary#getAmountFactory(javax.money.MonetaryAmountFactoryQuery) - */ - enum QueryInclusionPolicy{ - /** - * Always include this factory (and the corresponding amount type) within queries. This is - * the default for normal {@link MonetaryAmount} implementation types. - */ - ALWAYS, - /** - * Only consider this factory, when the implementation type is specified explicitly in the - * {@link MonetaryContext} required. - */ - DIRECT_REFERENCE_ONLY, - /** - * Never consider this factory in a query for a matching {@link MonetaryAmount} - * implementation. - */ - NEVER - } - - - /** - * Method that determines if this factory should be considered for general evaluation of - * matching {@link MonetaryAmount} implementation types when calling - * {@link javax.money.Monetary#getAmountFactory(javax.money.MonetaryAmountFactoryQuery)}. - * - * @return {@code true} to include this factory into the evaluation. - * @see javax.money.Monetary#getAmountFactory(javax.money.MonetaryAmountFactoryQuery) - */ - default QueryInclusionPolicy getQueryInclusionPolicy(){ - return QueryInclusionPolicy.ALWAYS; - } - - /** - * Get the concrete amount type created by {@link javax.money.MonetaryAmountFactory} instances provided. - * - * @return the concrete amount type created, never null. - */ - Class getAmountType(); - - /** - * Access a {@link javax.money.MonetaryAmountFactory} given the required context. - * - * @return the corresponding {@link javax.money.MonetaryAmountFactory}, or {@code null}. - */ - MonetaryAmountFactory createMonetaryAmountFactory(); - - /** - * Returns the default {@link MonetaryContext} used, when no {@link MonetaryContext} is - * provided. - *

- * The default context is not allowed to exceed the capabilities of the maximal - * {@link MonetaryContext} supported. - * - * @return the default {@link MonetaryContext}, never {@code null}. - * @see #getMaximalMonetaryContext() - */ - MonetaryContext getDefaultMonetaryContext(); - - /** - * Returns the maximal {@link MonetaryContext} supported, for requests that exceed these maximal - * capabilities, an {@link ArithmeticException} must be thrown. - * - * @return the maximal {@link MonetaryContext} supported, never {@code null} - */ - default MonetaryContext getMaximalMonetaryContext(){ - return getDefaultMonetaryContext(); - } - -} diff --git a/src/main/java/javax/money/spi/MonetaryAmountFormatProviderSpi.java b/src/main/java/javax/money/spi/MonetaryAmountFormatProviderSpi.java deleted file mode 100644 index 288e51e40..000000000 --- a/src/main/java/javax/money/spi/MonetaryAmountFormatProviderSpi.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import javax.money.format.AmountFormatQuery; -import javax.money.format.MonetaryAmountFormat; -import java.util.Collection; -import java.util.Locale; -import java.util.Set; - -/** - * SPI (formatting) providing {@link MonetaryAmountFormat} instances. - * - * @author Anatole Tresch - */ -public interface MonetaryAmountFormatProviderSpi { - - /** - * Access the provider's name. - * @return this provider's name, not null. - */ - default String getProviderName(){ - return getClass().getSimpleName(); - } - - /** - * Create a new {@link MonetaryAmountFormat} for the given input. - * - * @param formatQuery - * The {@link javax.money.format.AmountFormatContext} to be used. - * @return An according {@link MonetaryAmountFormat} instance, or {@code null}, which delegates - * the request to subsequent {@link MonetaryAmountFormatProviderSpi} instances - * registered. - */ - Collection getAmountFormats(AmountFormatQuery formatQuery); - - /** - * Gets a list with available locales for this format provider. - * @return list of available locales, never null. - */ - Set getAvailableLocales(); - - /** - * Gets a list with available format names for this format provider. - * @return list of available formats, never null. - */ - Set getAvailableFormatNames(); -} diff --git a/src/main/java/javax/money/spi/MonetaryAmountsSingletonQuerySpi.java b/src/main/java/javax/money/spi/MonetaryAmountsSingletonQuerySpi.java deleted file mode 100644 index 2f060228a..000000000 --- a/src/main/java/javax/money/spi/MonetaryAmountsSingletonQuerySpi.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import javax.money.MonetaryAmount; -import javax.money.MonetaryAmountFactory; -import javax.money.MonetaryAmountFactoryQuery; - -import java.util.Collection; -import java.util.stream.Collectors; - -/** - * SPI (core) for the backing implementation of the {@link javax.money.Monetary} singleton, implementing - * the query functionality for amounts. - * - * @author Anatole Tresch - */ -public interface MonetaryAmountsSingletonQuerySpi { - - /** - * Get the {@link javax.money.MonetaryAmountFactory} implementation class, that best matches to cover the given - * {@link javax.money.MonetaryContext}. - *

- * The evaluation order should consider the following aspects: - *

    - *
  • If {@link javax.money.MonetaryContext#getAmountType()} is explicitly defined, it should be considered. - * Nevertheless if precision/scale cannot be met, a {@link javax.money.MonetaryException} should - * be thrown. - *
  • The remaining implementation class candidates must cover the required precision. - *
  • The remaining implementation class candidates must cover the required max scale. - *
  • If max scale is met, but {@code precision==0} (unlimited precision), the - * {@link javax.money.MonetaryAmount} implementation candidate should be chosen with highest possible - * precision. - *
  • If still multiple implementation candidates qualify, the ones with - * {@code Flavor.PERFORMANCE} are preferred. - *
  • After this point the selection may be arbitrary. - *
- * - * @param query the factory query, not null. - * @return the {@link javax.money.MonetaryAmount} implementation class, that best matches to cover the given - * {@link javax.money.MonetaryContext}, never {@code null}. - * @throws javax.money.MonetaryException if no {@link javax.money.MonetaryAmount} implementation class can cover - * the required - * {@link javax.money.MonetaryContext}. - */ - Collection> getAmountFactories(MonetaryAmountFactoryQuery query); - - /** - * Checks if an {@link javax.money.MonetaryAmountFactory} is matching the given query. - * - * @param query the factory query, not null. - * @return true, if at least one {@link javax.money.MonetaryAmountFactory} matches the query. - */ - default boolean isAvailable(MonetaryAmountFactoryQuery query) { - return !getAmountFactories(query).isEmpty(); - } - - /** - * Executes the query and returns the {@link javax.money.MonetaryAmount} implementation type found, - * if there is only one type. - * If multiple types match the query, the first one is selected. - * - * @param query the factory query, not null. - * @return the type found, or null. - */ - default Class getAmountType(MonetaryAmountFactoryQuery query) { - MonetaryAmountFactory f = getAmountFactory(query); - if (f != null) { - return f.getAmountType(); - } - return null; - } - - /** - * Executes the query and returns the {@link javax.money.MonetaryAmount} implementation types found. - * - * @param query the factory query, not null. - * @return the type found, or null. - */ - default Collection> getAmountTypes(MonetaryAmountFactoryQuery query) { - Collection> factories = getAmountFactories(query); - return factories.stream().map(MonetaryAmountFactory::getAmountType).collect(Collectors.toList()); - } - - /** - * Executes the query and returns the {@link javax.money.MonetaryAmountFactory} implementation type found, - * if there is only one type. If multiple types match the query, the first one is selected. - * - * @param query the factory query, not null. - * @return the type found, or null. - */ - @SuppressWarnings("rawtypes") - default MonetaryAmountFactory getAmountFactory(MonetaryAmountFactoryQuery query) { - Collection> factories = getAmountFactories(query); - if (factories.isEmpty()) { - return null; - } - return factories.iterator().next(); - } - -} diff --git a/src/main/java/javax/money/spi/MonetaryAmountsSingletonSpi.java b/src/main/java/javax/money/spi/MonetaryAmountsSingletonSpi.java deleted file mode 100644 index 3d6780acb..000000000 --- a/src/main/java/javax/money/spi/MonetaryAmountsSingletonSpi.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import javax.money.MonetaryAmount; -import javax.money.MonetaryAmountFactory; -import javax.money.MonetaryException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -/** - * SPI (core) for the backing implementation of the {@link javax.money.Monetary} singleton. It - * should load and manage (including contextual behavior), if needed) the different registered - * {@link javax.money.MonetaryAmountFactory} instances. - * - * @author Anatole Tresch - */ -public interface MonetaryAmountsSingletonSpi{ - - /** - * Access the {@link javax.money.MonetaryAmountFactory} for the given {@code amountType} . - * - * @param amountType the {@link MonetaryAmount} implementation type, targeted by the factory. - * @return the {@link javax.money.MonetaryAmountFactory}, or {@code null}, if no such - * {@link javax.money.MonetaryAmountFactory} is available in the current context. - */ - MonetaryAmountFactory getAmountFactory(Class amountType); - - /** - * Access the default {@link MonetaryAmount} implementation type. - * - * @return a the default {@link MonetaryAmount} type corresponding, never {@code null}. - * @throws MonetaryException if no {@link MonetaryAmountFactoryProviderSpi} is available, or no - * {@link MonetaryAmountFactoryProviderSpi} targeting the configured default - * {@link MonetaryAmount} type. - * @see javax.money.Monetary#getDefaultAmountType() - */ - Class getDefaultAmountType(); - - /** - * Get the currently registered {@link MonetaryAmount} implementation types. - * - * @return the {@link Set} if registered {@link MonetaryAmount} implementations, never - * {@code null}. - */ - Collection> getAmountTypes(); - - - /** - * Access the default {@link javax.money.MonetaryAmountFactory}. - * - * @return a the default {@link MonetaryAmount} type corresponding, never {@code null}. - * @throws MonetaryException if no {@link MonetaryAmountFactoryProviderSpi} is available, or no - * {@link MonetaryAmountFactoryProviderSpi} targeting the configured default - * {@link MonetaryAmount} type. - * @see javax.money.Monetary#getDefaultAmountType() - */ - default MonetaryAmountFactory getDefaultAmountFactory(){ - return getAmountFactory(getDefaultAmountType()); - } - - /** - * Get the currently registered {@link MonetaryAmount} implementation classes. - * - * @return the {@link Set} if registered {@link MonetaryAmount} implementations, never - * {@code null}. - */ - default Collection> getAmountFactories(){ - List> factories = new ArrayList<>(); - for(Class type : getAmountTypes()){ - factories.add(getAmountFactory(type)); - } - return factories; - } - -} \ No newline at end of file diff --git a/src/main/java/javax/money/spi/MonetaryConversionsSingletonSpi.java b/src/main/java/javax/money/spi/MonetaryConversionsSingletonSpi.java deleted file mode 100644 index b4141eac9..000000000 --- a/src/main/java/javax/money/spi/MonetaryConversionsSingletonSpi.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import java.util.*; - -import javax.money.CurrencyUnit; -import javax.money.MonetaryException; -import javax.money.convert.*; - -/** - * SPI (conversion) that implements the functionality provided by the - * {@code MonetaryConversions} singleton accessor. It should be registered as a - * service using the JDK {@code ServiceLoader}. Hereby only one instance can be - * registered at a time. - *

- * This interface is designed to support also contextual behaviour, e.g. in Java - * EE containers each application may provide its own - * {@link ExchangeRateProvider} instances, e.g. by registering them as CDI - * beans. An EE container can register an according - * {@link MonetaryConversionsSingletonSpi} that manages the different application - * contexts transparently. In a SE environment this class is expected to behave - * like an ordinary singleton, loading its SPIs from the {@link ServiceLoader}. - *

- * Instances of this class must be thread safe. It is not a requirement that - * they are serializable. - *

- * Only one instance can be registered using the {@link ServiceLoader}. When - * registering multiple instances the {@link MonetaryConversions} accessor will - * not work. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public interface MonetaryConversionsSingletonSpi { - - /** - * Get all currently registered provider names. - * - * @return all currently registered provider names - * @see ProviderContext#getProviderName() - */ - Collection getProviderNames(); - - - /** - * Get the default provider chain used. The ordering of the items is the - * access order/precedence of the providers. - * - * @return the default provider chain, not {@code null} and not empty. - */ - List getDefaultProviderChain(); - - /** - * Access an instance of {@link ExchangeRateProvider}. By setting {@link javax.money.convert - * .ConversionQuery#getCurrencyProviderNames()} multiple providers can be selected, - * that will be included into a compound instance, with the same order as returned by the {@link javax - * .money.convert.ConversionQuery}. - * - * @param conversionQuery the {@link javax.money.convert.ConversionQuery} determining the type of conversion - * required, not null. - * @return an {@link ExchangeRateProvider} built up with the given sub - * providers, never {@code null} - * @throws MonetaryException if a provider could not be found. - * @see #isExchangeRateProviderAvailable(javax.money.convert.ConversionQuery) - */ - ExchangeRateProvider getExchangeRateProvider(ConversionQuery conversionQuery); - - /** - * Allows to quickly check, if a {@link javax.money.convert.ExchangeRateProvider} is accessible for the given - * {@link javax.money.convert.ConversionQuery}. - * - * @param conversionQuery the {@link javax.money.convert.ConversionQuery} determining the type of conversion - * required, not null. - * @return {@code true}, if such a conversion is supported, meaning an according - * {@link ExchangeRateProvider} can be - * accessed. - * @see #getExchangeRateProvider(ConversionQuery) - * @see #getExchangeRateProvider(String...) - */ - default boolean isExchangeRateProviderAvailable(ConversionQuery conversionQuery) { - try { - return getExchangeRateProvider(conversionQuery) != null; - } catch (Exception e) { - return false; - } - } - - /** - * Allows to quickly check, if a {@link javax.money.convert.CurrencyConversion} is accessible for the given - * {@link javax.money.convert.ConversionQuery}. - * - * @param conversionQuery the {@link javax.money.convert.ConversionQuery} determining the type of conversion - * required, not null. - * @return {@code true}, if such a conversion is supported, meaning an according - * {@link CurrencyConversion} can be - * accessed. - * @see #getConversion(javax.money.convert.ConversionQuery) - * @see #getConversion(CurrencyUnit, String...) - */ - default boolean isConversionAvailable(ConversionQuery conversionQuery) { - try { - return getConversion(conversionQuery) != null; - } catch (Exception e) { - return false; - } - } - - /** - * Allows to quickly check, if a {@link javax.money.convert.CurrencyConversion} is accessible for the given - * {@link javax.money.convert.ConversionQuery}. - * - * @param termCurrency the terminating/target currency unit, not null. - * @param providers the provider names defines a corresponding - * provider chain that must be encapsulated by the resulting {@link javax - * .money.convert.CurrencyConversion}. By default the provider - * chain as defined by #getDefaultCurrencyProviderChain will be used. - * @return {@code true}, if such a conversion is supported, meaning an according - * {@link CurrencyConversion} can be - * accessed. - * @see #getConversion(javax.money.convert.ConversionQuery) - * @see #getConversion(CurrencyUnit, String...) - */ - default boolean isConversionAvailable(CurrencyUnit termCurrency, String... providers) { - return isConversionAvailable( - ConversionQueryBuilder.of().setTermCurrency(termCurrency).setProviderNames(providers).build()); - } - - /** - * Access the current registered {@link javax.money.convert.ExchangeRateProvider} instances. If no provider - * names are passed ALL current registered providers are returned in undefined order. - * - * @param providers the provider names of the providers to be accessed - * @return the list of providers, in the same order as requested. - * @throws MonetaryException if a provider could not be resolved. - */ - default List getExchangeRateProviders(String... providers) { - List provInstances = new ArrayList<>(); - Collection providerNames = Arrays.asList(providers); - if (providerNames.isEmpty()) { - providerNames = getProviderNames(); - } - for (String provName : providerNames) { - provInstances.add(Optional.ofNullable(getExchangeRateProvider(provName)).orElseThrow( - () -> new MonetaryException("Unsupported conversion/rate provider: " + provName))); - } - return provInstances; - } - - /** - * Access a compound instance of an {@link ExchangeRateProvider} based on the given provider chain. - * - * @param providers the {@link javax.money.convert.ConversionQuery} provider names defines a corresponding - * provider chain that must be - * encapsulated by the resulting {@link javax.money.convert.ExchangeRateProvider}. By default - * the default - * provider changes as defined in #getDefaultCurrencyProviderChain will be used. - * @return an {@link ExchangeRateProvider} built up with the given sub - * providers, never {@code null}. - * @throws MonetaryException if a provider listed could not be found. - * @see #getProviderNames() - * @see #isExchangeRateProviderAvailable(javax.money.convert.ConversionQuery) - */ - default ExchangeRateProvider getExchangeRateProvider(String... providers) { - return getExchangeRateProvider(ConversionQueryBuilder.of().setProviderNames(providers).build()); - } - - /** - * Access an instance of {@link CurrencyConversion}. - * - * @param conversionQuery the {@link javax.money.convert.ConversionQuery} determining the type of conversion - * required, not null. - * @return the corresponding conversion, not null. - * @throws javax.money.MonetaryException if no matching conversion could be found. - * @see #isConversionAvailable(javax.money.convert.ConversionQuery) - */ - default CurrencyConversion getConversion(ConversionQuery conversionQuery) { - return getExchangeRateProvider(conversionQuery).getCurrencyConversion( - Objects.requireNonNull(conversionQuery.getCurrency(), "Terminating Currency is required.") - ); - } - - /** - * Access an instance of {@link CurrencyConversion}. - * - * @param termCurrency the terminating/target currency unit, not null. - * @param providers the {@link javax.money.convert.ConversionQuery} provider names defines a corresponding - * provider chain that must be encapsulated by the resulting {@link javax - * .money.convert.CurrencyConversion}. By default the default - * provider chain as defined by #getDefaultCurrencyProviderChain will be used. - * @return the corresponding conversion, not null. - * @throws javax.money.MonetaryException if no matching conversion could be found. - * @see #isConversionAvailable(javax.money.convert.ConversionQuery) - */ - default CurrencyConversion getConversion(CurrencyUnit termCurrency, String... providers) { - return getConversion(ConversionQueryBuilder.of().setTermCurrency(termCurrency).setProviderNames(providers).build()); - } - -} diff --git a/src/main/java/javax/money/spi/MonetaryCurrenciesSingletonSpi.java b/src/main/java/javax/money/spi/MonetaryCurrenciesSingletonSpi.java deleted file mode 100644 index fa57c6189..000000000 --- a/src/main/java/javax/money/spi/MonetaryCurrenciesSingletonSpi.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import javax.money.*; -import java.util.*; - -/** - * Factory singleton backing interface for {@link javax.money.Monetary} that provides access to - * different registered {@link javax.money.spi.CurrencyProviderSpi} instances. - *

- * Implementations of this interface must be thread safe. - * - * @author Anatole Tresch - * @version 0.8 - */ -public interface MonetaryCurrenciesSingletonSpi { - - /** - * Access a list of the currently registered default providers. The default providers are used, when - * no provider names are passed by the caller. - * - * @return the currencies returned by the given provider chain. If not provider names are provided - * the default provider chain configured in {@code javamoney.properties} is used. - * @see #getCurrencies(String...) - * @see javax.money.CurrencyQueryBuilder - */ - List getDefaultProviderChain(); - - /** - * Access a list of the currently registered providers. The names can be used to - * access subsets of the overall currency range by calling {@link #getCurrencies(String...)}. - * - * @return the currencies returned by the given provider chain. If not provider names are provided - * the default provider chain configured in {@code javamoney.properties} is used. - */ - Set getProviderNames(); - - /** - * Access all currencies matching the given query. - * - * @param query The currency query, not null. - * @return a set of all currencies found, never null. - */ - Set getCurrencies(CurrencyQuery query); - - - /** - * Access a new instance based on the currency code. Currencies are - * available as provided by {@link javax.money.spi.CurrencyProviderSpi} instances registered - * with the {@link Bootstrap}. - * - * @param currencyCode the ISO currency code, not {@code null}. - * @param providers the (optional) specification of providers to consider. If not set (empty) the providers - * as defined by #getDefaultCurrencyProviderChain() should be used. - * @return the corresponding {@link javax.money.CurrencyUnit} instance. - * @throws javax.money.UnknownCurrencyException if no such currency exists. - */ - default CurrencyUnit getCurrency(String currencyCode, String... providers) { - Objects.requireNonNull(currencyCode, "Currency Code may not be null"); - Collection found = - getCurrencies(CurrencyQueryBuilder.of().setCurrencyCodes(currencyCode).setProviderNames(providers).build()); - if (found.isEmpty()) { - throw new UnknownCurrencyException(currencyCode); - } - if (found.size() > 1) { - throw new MonetaryException("Ambiguous CurrencyUnit for code: " + currencyCode + ": " + found); - } - return found.iterator().next(); - } - - /** - * Access a new instance based on the currency code. Currencies are - * available as provided by {@link javax.money.spi.CurrencyProviderSpi} instances registered - * with the {@link Bootstrap}. - * - * @param country the ISO currency's country, not {@code null}. - * @param providers the (optional) specification of providers to consider. If not set (empty) the providers - * as defined by #getDefaultCurrencyProviderChain() should be used. - * @return the corresponding {@link javax.money.CurrencyUnit} instance. - * @throws javax.money.UnknownCurrencyException if no such currency exists. - */ - default CurrencyUnit getCurrency(Locale country, String... providers) { - Collection found = - getCurrencies(CurrencyQueryBuilder.of().setCountries(country).setProviderNames(providers).build()); - if (found.isEmpty()) { - throw new MonetaryException("No currency unit found for locale: " + country); - } - if (found.size() > 1) { - throw new MonetaryException("Ambiguous CurrencyUnit for locale: " + country + ": " + found); - } - return found.iterator().next(); - } - - /** - * Provide access to all currently known currencies. - * - * @param locale the target {@link java.util.Locale}, typically representing an ISO country, - * not {@code null}. - * @param providers the (optional) specification of providers to consider. If not set (empty) the providers - * as defined by #getDefaultCurrencyProviderChain() should be used. - * @return a collection of all known currencies, never null. - */ - default Set getCurrencies(Locale locale, String... providers) { - return getCurrencies(CurrencyQueryBuilder.of().setCountries(locale).setProviderNames(providers).build()); - } - - /** - * Allows to check if a {@link javax.money.CurrencyUnit} instance is defined, i.e. - * accessible from {@link javax.money.spi.MonetaryCurrenciesSingletonSpi#getCurrency(String, String...)}. - * - * @param code the currency code, not {@code null}. - * @param providers the (optional) specification of providers to consider. If not set (empty) the providers - * as defined by #getDefaultCurrencyProviderChain() should be used. - * @return {@code true} if {@link javax.money.spi.MonetaryCurrenciesSingletonSpi#getCurrency(String, String...)} - * would return a result for the given code. - */ - default boolean isCurrencyAvailable(String code, String... providers) { - return !getCurrencies(CurrencyQueryBuilder.of().setCurrencyCodes(code).setProviderNames(providers).build()) - .isEmpty(); - } - - /** - * Allows to check if a {@link javax.money.CurrencyUnit} instance is - * defined, i.e. accessible from {@link #getCurrency(String, String...)}. - * - * @param locale the target {@link java.util.Locale}, not {@code null}. - * @param providers the (optional) specification of providers to consider. If not set (empty) the providers - * as defined by #getDefaultCurrencyProviderChain() should be used. - * @return {@code true} if {@link #getCurrencies(java.util.Locale, String...)} would return a - * non empty result for the given code. - */ - default boolean isCurrencyAvailable(Locale locale, String... providers) { - return !getCurrencies(CurrencyQueryBuilder.of().setCountries(locale).setProviderNames(providers).build()).isEmpty(); - } - - /** - * Provide access to all currently known currencies. - * - * @param providers the (optional) specification of providers to consider. If not set (empty) the providers - * as defined by #getDefaultCurrencyProviderChain() should be used. - * @return a collection of all known currencies, never null. - */ - default Set getCurrencies(String... providers) { - return getCurrencies(CurrencyQueryBuilder.of().setProviderNames(providers).build()); - } - - /** - * Access a single currency by query. - * - * @param query The currency query, not null. - * @return the {@link javax.money.CurrencyUnit} found, never null. - * @throws javax.money.MonetaryException if multiple currencies match the query. - */ - default CurrencyUnit getCurrency(CurrencyQuery query) { - Set currencies = getCurrencies(query); - if (currencies.isEmpty()) { - throw new MonetaryException("CurrencyUnit not found: " + query); - } - if (currencies.size() == 1) { - return currencies.iterator().next(); - } - throw new MonetaryException("Ambiguous request for CurrencyUnit: " + query + ", found: " + currencies); - } -} diff --git a/src/main/java/javax/money/spi/MonetaryFormatsSingletonSpi.java b/src/main/java/javax/money/spi/MonetaryFormatsSingletonSpi.java deleted file mode 100644 index 9eb48c049..000000000 --- a/src/main/java/javax/money/spi/MonetaryFormatsSingletonSpi.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import javax.money.MonetaryException; -import javax.money.format.AmountFormatQuery; -import javax.money.format.AmountFormatQueryBuilder; -import javax.money.format.MonetaryAmountFormat; -import java.util.*; - -/** - * This interface models the singleton functionality of {@link javax.money.format.MonetaryFormats}. - *

- * Implementations of this interface must be thread-safe. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public interface MonetaryFormatsSingletonSpi { - - /** - * Get all available locales. This equals to {@link MonetaryAmountFormatProviderSpi#getAvailableLocales()}. - * - * @param providers The (optional) providers to be used, ordered correspondingly. - * @return all available locales, never {@code null}. - */ - Set getAvailableLocales(String... providers); - - /** - * Access all {@link javax.money.format.MonetaryAmountFormat} instances matching the given {@link javax.money.format - * .AmountFormatQuery}. - * - * @param formatQuery The format query defining the requirements of the formatter. - * @return the corresponding {@link javax.money.format.MonetaryAmountFormat} instances, never null - */ - Collection getAmountFormats(AmountFormatQuery formatQuery); - - /** - * Get the names of the currently registered format providers. - * - * @return the provider names, never null. - */ - Set getProviderNames(); - - /** - * Get the default provider chain, identified by the unique provider names in order as evaluated and used. - * - * @return the default provider chain, never null. - */ - List getDefaultProviderChain(); - - /** - * Access an {@link javax.money.format.MonetaryAmountFormat} given a {@link javax.money.format - * .AmountFormatQuery}. - * - * @param formatQuery The format query defining the requirements of the formatter. - * @return the corresponding {@link javax.money.format.MonetaryAmountFormat} - * @throws javax.money.MonetaryException if no registered {@link javax.money.spi - * .MonetaryAmountFormatProviderSpi} can provide a - * corresponding {@link javax.money.format.MonetaryAmountFormat} instance. - */ - default MonetaryAmountFormat getAmountFormat(AmountFormatQuery formatQuery) { - Collection formats = getAmountFormats(formatQuery); - if (formats.isEmpty()) { - throw new MonetaryException("No MonetaryAmountFormat for AmountFormatQuery " + formatQuery); - } - return formats.iterator().next(); - } - - /** - * Checks if a {@link javax.money.format.MonetaryAmountFormat} is available given a {@link javax.money.format - * .AmountFormatQuery}. - * - * @param formatQuery The format query defining the requirements of the formatter. - * @return true, if a t least one {@link javax.money.format.MonetaryAmountFormat} is matching the query. - */ - default boolean isAvailable(AmountFormatQuery formatQuery) { - return !getAmountFormats(formatQuery).isEmpty(); - } - - /** - * Checks if a {@link javax.money.format.MonetaryAmountFormat} is available given a {@link javax.money.format - * .AmountFormatQuery}. - * - * @param locale the target {@link Locale}, not {@code null}. - * @param providers The (optional) providers to be used, ordered correspondingly. - * @return true, if a t least one {@link javax.money.format.MonetaryAmountFormat} is matching the query. - */ - default boolean isAvailable(Locale locale, String... providers) { - return isAvailable(AmountFormatQuery.of(locale, providers)); - } - - /** - * Access the default {@link MonetaryAmountFormat} given a {@link Locale}. - * - * @param locale the target {@link Locale}, not {@code null}. - * @param providers The (optional) providers to be used, ordered correspondingly. - * @return the matching {@link MonetaryAmountFormat} - * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a - * corresponding {@link MonetaryAmountFormat} instance. - */ - default MonetaryAmountFormat getAmountFormat(Locale locale, String... providers) { - return getAmountFormat(AmountFormatQueryBuilder.of(locale).setProviderNames(providers).build()); - } - - /** - * Access the default {@link MonetaryAmountFormat} given a {@link Locale}. - * - * @param formatName the target format name, not {@code null}. - * @param providers The (optional) providers to be used, ordered correspondingly. - * @return the matching {@link MonetaryAmountFormat} - * @throws MonetaryException if no registered {@link MonetaryAmountFormatProviderSpi} can provide a - * corresponding {@link MonetaryAmountFormat} instance. - */ - default MonetaryAmountFormat getAmountFormat(String formatName, String... providers) { - return getAmountFormat(AmountFormatQueryBuilder.of(formatName).setProviderNames(providers).build()); - } - -} diff --git a/src/main/java/javax/money/spi/MonetaryRoundingsSingletonSpi.java b/src/main/java/javax/money/spi/MonetaryRoundingsSingletonSpi.java deleted file mode 100644 index df1a2ded1..000000000 --- a/src/main/java/javax/money/spi/MonetaryRoundingsSingletonSpi.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import javax.money.*; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -/** - * This class models the accessor for rounding instances, modeled as - * {@link javax.money.MonetaryOperator}. - *

- * This class is thread-safe. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public interface MonetaryRoundingsSingletonSpi { - - /** - * Allows to access the names of the current defined roundings. - * - * @param providers the providers and ordering to be used. By default providers and ordering as defined in - * #getDefaultProviders is used. - * @return the set of custom rounding ids, never {@code null}. - */ - Set getRoundingNames(String... providers); - - /** - * Allows to access the names of the current registered rounding providers. - * - * @return the set of provider names, never {@code null}. - */ - Set getProviderNames(); - - /** - * Access a list of the currently registered default providers. The default providers are used, when - * no provider names are passed by the caller. - * - * @return the provider names in order, defining the provider chain. - * The default provider chain configured in {@code javamoney.properties} is used. - * @see javax.money.RoundingQueryBuilder - */ - List getDefaultProviderChain(); - - /** - * Execute a query for {@link javax.money.MonetaryRounding}. This allows to model more complex used cases, - * such as historic or special roundings. - * - * @param query the query to be expected, not null. - * @return the roundings found, never null. - */ - Collection getRoundings(RoundingQuery query); - - - /** - * Creates a {@link MonetaryRounding} that can be added as {@link javax.money.MonetaryOperator} to - * chained calculations. The instance must lookup the concrete - * {@link javax.money.MonetaryRounding} instance from the {@link javax.money.spi.MonetaryRoundingsSingletonSpi} - * based on the input {@link javax.money.MonetaryAmount}'s {@link javax.money.CurrencyUnit}. - * - * @return the (shared) default rounding instance. - */ - MonetaryRounding getDefaultRounding(); - - /** - * Access a {@link javax.money.MonetaryRounding} for rounding {@link javax.money.MonetaryAmount} - * instances given a currency. - * - * @param currencyUnit The currency, which determines the required precision. As - * {@link java.math.RoundingMode}, by default, {@link java.math.RoundingMode#HALF_UP} - * is sued. - * @param providers the optional provider list and ordering to be used - * @return a new instance {@link javax.money.MonetaryOperator} implementing the - * rounding, never {@code null}. - * @throws MonetaryException if no such rounding could be provided. - */ - default MonetaryRounding getRounding(CurrencyUnit currencyUnit, String... providers) { - MonetaryRounding op = - getRounding(RoundingQueryBuilder.of().setProviderNames(providers).setCurrency(currencyUnit).build()); - return Optional.ofNullable(op).orElseThrow(() -> new MonetaryException( - "No rounding provided for CurrencyUnit: " + currencyUnit.getCurrencyCode())); - } - - - /** - * Access a {@link javax.money.MonetaryRounding} using the rounding name. - * - * @param roundingName The rounding name, not null. - * @param providers the optional provider list and ordering to be used - * @return the corresponding {@link javax.money.MonetaryOperator} implementing the - * rounding, never {@code null}. - * @throws IllegalArgumentException if no such rounding is registered using a - * {@link javax.money.spi.RoundingProviderSpi} instance. - */ - default MonetaryRounding getRounding(String roundingName, String... providers) { - MonetaryRounding op = - getRounding(RoundingQueryBuilder.of().setProviderNames(providers).setRoundingName(roundingName).build()); - return Optional.ofNullable(op) - .orElseThrow(() -> new MonetaryException("No rounding provided with rounding name: " + roundingName)); - } - - - /** - * Query a specific rounding with the given query. If multiple roundings match the query the first one is - * selected, since the query allows to determine the providers and their ordering by setting {@link - * RoundingQuery#getProviderNames()}. - * - * @param query the rounding query, not null. - * @return the rounding found, or null, if no rounding matches the query. - */ - default MonetaryRounding getRounding(RoundingQuery query) { - Collection roundings = getRoundings(query); - if (roundings.isEmpty()) { - return null; - } - return roundings.iterator().next(); - } - - /** - * Checks if any {@link javax.money.MonetaryRounding} is matching the given query. - * - * @param query the rounding query, not null. - * @return true, if at least one rounding matches the query. - */ - default boolean isRoundingAvailable(RoundingQuery query) { - return !getRoundings(query).isEmpty(); - } - - /** - * Checks if a {@link MonetaryRounding} is available given a roundingId. - * - * @param roundingId The rounding identifier. - * @param providers the providers and ordering to be used. By default providers and ordering as defined in - * #getDefaultProviders is used. - * @return true, if a corresponding {@link javax.money.MonetaryRounding} is available. - * @throws IllegalArgumentException if no such rounding is registered using a - * {@link RoundingProviderSpi} instance. - */ - default boolean isRoundingAvailable(String roundingId, String... providers) { - return isRoundingAvailable( - RoundingQueryBuilder.of().setProviderNames(providers).setRoundingName(roundingId).build()); - } - - /** - * Checks if a {@link MonetaryRounding} is available given a {@link javax.money.CurrencyUnit}. - * - * @param currencyUnit The currency, which determines the required precision. As {@link java.math.RoundingMode}, - * by default, {@link java.math.RoundingMode#HALF_UP} is used. - * @param providers the providers and ordering to be used. By default providers and ordering as defined in - * #getDefaultProviders is used. - * @return true, if a corresponding {@link javax.money.MonetaryRounding} is available. - * @throws IllegalArgumentException if no such rounding is registered using a - * {@link RoundingProviderSpi} instance. - */ - default boolean isRoundingAvailable(CurrencyUnit currencyUnit, String... providers) { - return isRoundingAvailable(RoundingQueryBuilder.of().setProviderNames(providers).setCurrency(currencyUnit).build()); - } -} diff --git a/src/main/java/javax/money/spi/RoundingProviderSpi.java b/src/main/java/javax/money/spi/RoundingProviderSpi.java deleted file mode 100644 index c55260cd1..000000000 --- a/src/main/java/javax/money/spi/RoundingProviderSpi.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import java.util.Set; - -import javax.money.*; - -/** - * This SPI allows to extends/override the roundings available for - * {@link CurrencyUnit}. The JSRs implementation already provides default - * roundings. By registering instances of this interface using the - * {@link javax.money.spi.Bootstrap}, the default behaviour can be - * overridden and extended, e.g. for supporting also special roundings. - *

- * Implementations of this interface must be - *

    - *
  • thread-safe - *
  • not require loading of other resources. - *
- * If required, it is possible to implement this interface in a contextual way, - * e.g. providing different roundings depending on the current EE application - * context. Though in most cases rounding should be a general concept that does - * not require contextual handling. - * - * @author Anatole Tresch - */ -public interface RoundingProviderSpi { - - /** - * Evaluate the rounding that match the given query. - * @param query the rounding query. - * @return the matching rounding instance, or {@code null}. - */ - MonetaryRounding getRounding(RoundingQuery query); - - /** - * Access the ids of the roundings defined by this provider. - * - * @return the ids of the defined roundings, never {@code null}. - */ - Set getRoundingNames(); - - /** - * Get the provider's unique name. - * @return the provider's unique name, not {@code null}. - */ - default String getProviderName(){ - return getClass().getSimpleName(); - } - - -} diff --git a/src/main/java/javax/money/spi/ServiceProvider.java b/src/main/java/javax/money/spi/ServiceProvider.java deleted file mode 100644 index 9ac8d09b8..000000000 --- a/src/main/java/javax/money/spi/ServiceProvider.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import java.util.List; - -/** - * This class models the component that is managing the lifecycle of the - * monetary services used by the Money and Currency API. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public interface ServiceProvider { - - /** - * This method allows to define a priority for a registered ServiceProvider instance. When multiple providers are - * registered in the system the provider with the highest priority value is taken. - * - * @return the provider's priority (default is 0). - */ - int getPriority(); - - /** - * Access a list of services, given its type. The bootstrap mechanism should - * order the instance for precedence, hereby the most significant should be - * first in order. If no such services are found, an empty list should be - * returned. - * - * @param serviceType the service type. - * @return The instance to be used, never {@code null} - */ - List getServices(Class serviceType); - - /** - * Access a single service, given its type. The bootstrap mechanism should - * order the instance for precedence, hereby the most significant should be - * first in order and returned. If no such services are found, null is - * returned. - * - * @param serviceType the service type. - * @return The instance, (with highest precedence) or {@code null}, if no such service is available. - */ - default T getService(Class serviceType) { - return getServices(serviceType).stream().findFirst().orElse(null); - } -} diff --git a/src/main/java/javax/money/spi/package-info.java b/src/main/java/javax/money/spi/package-info.java deleted file mode 100644 index 6a1b8bddb..000000000 --- a/src/main/java/javax/money/spi/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * SPI interfaces of the Money and Currency API, including bootstrap logic. - */ -package javax.money.spi; - diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java deleted file mode 100644 index 6ad97b653..000000000 --- a/src/main/java/module-info.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module java.money { - exports javax.money; - exports javax.money.convert; - exports javax.money.format; - exports javax.money.spi; - requires java.base; - requires java.logging; - uses javax.money.spi.CurrencyProviderSpi; - uses javax.money.spi.MonetaryAmountFactoryProviderSpi; - uses javax.money.spi.MonetaryAmountFormatProviderSpi; - uses javax.money.spi.MonetaryAmountsSingletonQuerySpi; - uses javax.money.spi.MonetaryAmountsSingletonSpi; - uses javax.money.spi.MonetaryConversionsSingletonSpi; - uses javax.money.spi.MonetaryCurrenciesSingletonSpi; - uses javax.money.spi.MonetaryFormatsSingletonSpi; - uses javax.money.spi.MonetaryRoundingsSingletonSpi; - uses javax.money.spi.RoundingProviderSpi; - uses javax.money.spi.ServiceProvider; - uses javax.money.convert.ExchangeRateProvider; -} \ No newline at end of file diff --git a/src/site/site.xml b/src/site/site.xml deleted file mode 100644 index 2fdc974ea..000000000 --- a/src/site/site.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - JCP.org - - https://jcp.org/en/jsr/detail?id=354 - - - Java Money API - - https://javamoney.github.io/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/do-not-delete.txt b/src/test/do-not-delete.txt deleted file mode 100644 index e4bd809b9..000000000 --- a/src/test/do-not-delete.txt +++ /dev/null @@ -1,22 +0,0 @@ -==== - Copyright 2012-2016 Credit Suisse - Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==== - -==== - CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" BUTTON AT THE BOTTOM OF THIS PAGE. - - Specification: ("Specification") -==== diff --git a/src/test/java/javax/money/AbstractContextBuilderTest.java b/src/test/java/javax/money/AbstractContextBuilderTest.java deleted file mode 100644 index 1bc0318f7..000000000 --- a/src/test/java/javax/money/AbstractContextBuilderTest.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.testng.Assert.*; - -@SuppressWarnings("rawtypes") -public class AbstractContextBuilderTest { - - - @SuppressWarnings("unchecked") - private AbstractContextBuilder createBuilder() { - //noinspection unchecked - return new AbstractContextBuilder() { - @Override - public AbstractContext build() { - return new AbstractContext(this) { - private static final long serialVersionUID = -5720498720434069240L; - }; - } - }; - } - - @Test - public void testImportContext() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", BigDecimal.valueOf(10.0d)); - AbstractContext ctx = b.build(); - - AbstractContextBuilder b2 = createBuilder(); - b2.importContext(ctx); - AbstractContext ctx2 = b2.build(); - - assertEquals(ctx, ctx2); - assertEquals(ctx.get("myKey", BigDecimal.class), BigDecimal.valueOf(10.0d)); - assertEquals(ctx2.get("myKey", BigDecimal.class), BigDecimal.valueOf(10.0d)); - } - - @Test - public void testImportContext1() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", BigDecimal.valueOf(5.0d)); - AbstractContext ctx = b.build(); - - AbstractContextBuilder b2 = createBuilder(); - b2.set("myKey", BigDecimal.valueOf(10.0d)); - b2.importContext(ctx); - AbstractContext ctx2 = b2.build(); - - assertNotEquals(ctx, ctx2); - assertEquals(ctx.get("myKey", BigDecimal.class), BigDecimal.valueOf(5.0d)); - assertEquals(ctx2.get("myKey", BigDecimal.class), BigDecimal.valueOf(10.0d)); - } - - @Test - public void testSet_Int() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", 11); - AbstractContext ctx = b.build(); - assertEquals(ctx.getInt("myKey").intValue(), 11); - } - - @Test - public void testSet_Boolean() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", true); - AbstractContext ctx = b.build(); - assertEquals(ctx.getBoolean("myKey").booleanValue(), true); - } - - @Test - public void testSet_Long() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", 12345L); - AbstractContext ctx = b.build(); - assertEquals(ctx.getLong("myKey").longValue(), 12345L); - } - - @Test - public void testSet_Float() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", 1.5f); - AbstractContext ctx = b.build(); - assertEquals(ctx.getFloat("myKey"), 1.5f, 0.0f); - } - - @Test - public void testSet_Double() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", 1.5d); - AbstractContext ctx = b.build(); - assertEquals(ctx.getDouble("myKey"), 1.5d, 0.0d); - } - - @Test - public void testSet_String() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", "yes"); - AbstractContext ctx = b.build(); - assertEquals(ctx.getText("myKey"), "yes"); - } - - @Test - public void testSet7_Any() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", BigDecimal.valueOf(10.0d)); - AbstractContext ctx = b.build(); - assertEquals(ctx.get("myKey", BigDecimal.class), BigDecimal.valueOf(10.0d)); - } - - @Test - public void testSet_Any_Explicit() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", BigDecimal.valueOf(10.0d)); - AbstractContext ctx = b.build(); - assertEquals(ctx.get("myKey", Number.class), BigDecimal.valueOf(10.0d)); - } - - @Test - public void testSet_Object() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set(BigDecimal.valueOf(10.0d)); - AbstractContext ctx = b.build(); - assertEquals(ctx.get(BigDecimal.class), BigDecimal.valueOf(10.0d)); - } - - @Test - public void testSetCollection() throws Exception { - AbstractContextBuilder b = createBuilder(); - List list = new ArrayList<>(); - list.add(BigDecimal.ONE); - b.set("myKey", list); - AbstractContext ctx = b.build(); - assertEquals(ctx.get("myKey", List.class), list); - } - - @Test - public void testSetList() throws Exception { - AbstractContextBuilder b = createBuilder(); - List list = new ArrayList<>(); - list.add(BigDecimal.ONE); - b.set("myKey", list); - AbstractContext ctx = b.build(); - assertEquals(ctx.get("myKey", List.class), list); - } - - @Test - public void testSetMap() throws Exception { - AbstractContextBuilder b = createBuilder(); - List list = new ArrayList<>(); - list.add(BigDecimal.ONE); - b.set("myKey", list); - AbstractContext ctx = b.build(); - assertEquals(ctx.get("myKey", List.class), list); - } - - @Test - public void testSetSet() throws Exception { - AbstractContextBuilder b = createBuilder(); - Set set = new HashSet<>(); - set.add(BigDecimal.ONE); - b.set("myKey", set); - AbstractContext ctx = b.build(); - assertEquals(ctx.get("myKey", Set.class), set); - } - - @Test - public void testRemoveAttributes() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", "test"); - AbstractContext ctx = b.build(); - assertEquals(ctx.getText("myKey"), "test"); - b.removeAttributes("gugus"); - assertEquals(ctx.getText("myKey"), "test"); - b.removeAttributes("myKey"); - ctx = b.build(); - assertEquals(ctx.getText("myKey"), null); - } - - @Test - public void testToString() throws Exception { - AbstractContextBuilder b = createBuilder(); - b.set("myKey", "test"); - String toString = b.toString(); - assertNotNull(toString); - assertTrue(toString.contains("myKey")); - assertTrue(toString.contains("test")); - } -} \ No newline at end of file diff --git a/src/test/java/javax/money/AbstractContextTest.java b/src/test/java/javax/money/AbstractContextTest.java deleted file mode 100644 index b280c677e..000000000 --- a/src/test/java/javax/money/AbstractContextTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.testng.annotations.Test; - -/** - * Tests for {@link javax.money.AbstractContext}. - */ -public class AbstractContextTest { - @Test - public void testSet() { - TestContext ctx = new TestContext.Builder().set("Test").build(); - assertNotNull(ctx.get(String.class)); - assertEquals(ctx.get(String.class), "Test"); - assertEquals(ctx.get(String.class.getName(), String.class), "Test"); - assertEquals(ctx.get("String", String.class), null); - } - - @Test - public void testSetWithKey() { - TestContext ctx = new TestContext.Builder().set("myKey", "Test").build(); - assertNull(ctx.get(String.class)); - assertEquals("Test", ctx.get("myKey", String.class)); - assertEquals(ctx.get("myKey", String.class), "Test"); - assertEquals(ctx.get(String.class.getName(), String.class), null); - } - - @Test - public void testSetAll() { - TestContext ctx = new TestContext.Builder().set("myKey", "Test").build(); - TestContext ctx2 = new TestContext.Builder().importContext(ctx).build(); - assertEquals(ctx, ctx2); - } - - @Test - public void testSetWithKeyAndType() { - TestContext ctx = new TestContext.Builder().set("MyNum", 2).build(); - assertNull(ctx.get(String.class)); - assertEquals(Integer.valueOf(2), ctx.getInt("MyNum")); - assertEquals(ctx.get("MyNum", Number.class), 2); - assertNotNull(ctx.get("MyNum", Integer.class)); - } - - @Test - public void testHashCode() { - List contexts = new ArrayList<>(); - contexts.add(new TestContext.Builder().set("Test").set(1).set((long) 2).build()); - contexts.add(new TestContext.Builder().set("Test").set(2).set((long) 1).build()); - contexts.add(new TestContext.Builder().set("Test").set(2).build()); - contexts.add(new TestContext.Builder().set("Test").set((long) 2).build()); - contexts.add(new TestContext.Builder().set("Test").set(Boolean.TRUE).set("Test").build()); - Set hashCodes = new HashSet<>(); - contexts.forEach(ctx -> hashCodes.add(ctx.hashCode())); - // Check we have 5 distinct hash codes... - assertTrue(hashCodes.size() > 2); - } - - @Test - public void testEquals() { - List contexts = new ArrayList<>(); - contexts.add(new TestContext.Builder().set("Test").set(11).set((long) 2).build()); - contexts.add(new TestContext.Builder().set("Test").set(2).set((long) 11).build()); - contexts.add(new TestContext.Builder().set("Test").set(2).build()); - contexts.add(new TestContext.Builder().set("Test").set((long) 2).build()); - contexts.add(new TestContext.Builder().set("Test").set(Boolean.TRUE).set("Test").build()); - Set checkContexts = new HashSet<>(); - for (TestContext ctx : contexts) { - checkContexts.add(ctx); - checkContexts.add(ctx); - } - // Check we have 5 distinct hash codes... - assertTrue(checkContexts.size() == 5); - } - - @Test - public void testToString() { - TestContext ctx = new TestContext.Builder().set("Test").set(1).set((long) 2).build(); - assertNotNull(ctx.toString()); - assertTrue(ctx.toString().contains("1")); - assertTrue(ctx.toString().contains("2")); - assertTrue(ctx.toString().contains("Test")); - assertTrue(ctx.toString().contains("String")); - assertTrue(ctx.toString().contains("Integer")); - assertTrue(ctx.toString().contains("Long")); - assertTrue(ctx.toString().contains("TestContext")); - } - - @Test - public void testGetKeys() { - TestContext ctx = new TestContext.Builder().set("Test").set("a", 1).set("b", 2).build(); - Set keys = ctx.getKeys(String.class); - assertNotNull(keys); - assertFalse(keys.isEmpty()); - assertEquals(String.class.getName(), keys.iterator().next()); - keys = ctx.getKeys(Integer.class); - assertNotNull(keys); - assertTrue(keys.size() == 2); - assertTrue("a".equals(keys.iterator().next()) || "b".equals(keys.iterator().next())); - } - - @Test - public void testGetType() { - TestContext ctx = new TestContext.Builder().set("Test").set("a", 1).set("b", 2).build(); - assertEquals(String.class, ctx.getType(String.class.getName())); - assertEquals(Integer.class, ctx.getType("a")); - assertEquals(Integer.class, ctx.getType("b")); - } - - private static class TestContext extends AbstractContext { - - private static final long serialVersionUID = 1L; - - /** - * Private constructor, used by {@link AbstractContextBuilder}. - * - * @param builder the Builder. - */ - protected TestContext(@SuppressWarnings("rawtypes") AbstractContextBuilder builder) { - super(builder); - } - - private static final class Builder extends AbstractContextBuilder { - @Override - public TestContext build() { - return new TestContext(this); - } - } - - } - - -} diff --git a/src/test/java/javax/money/AbstractDynamicServiceProviderTest.java b/src/test/java/javax/money/AbstractDynamicServiceProviderTest.java deleted file mode 100644 index ccaaf2e55..000000000 --- a/src/test/java/javax/money/AbstractDynamicServiceProviderTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.money.spi.Bootstrap; -import javax.money.spi.CurrencyProviderSpi; -import javax.money.spi.ServiceProvider; - -import org.mockito.Mockito; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; - -/** - * Abstract test supporting to switch SPI implementations by using a ServiceProvider providing manually registered SPIs only. - * @author Matthias Hanisch - */ -public abstract class AbstractDynamicServiceProviderTest { - - private ServiceProvider originalServiceProvider; - private TestServiceProvider testServiceProvider; - - /** - * Initialized Bootstrap so that default ServiceProvider is enabled. Then stores the default ServiceProvider in - * {@link #originalServiceProvider}. Initializes Bootstrap with default ServiceProvider again so that it is - * usable in the Test. Also initialized {@link #testServiceProvider}. - */ - @BeforeMethod - public void prepare() { - Bootstrap.getService(CurrencyProviderSpi.class); - ServiceProvider empty = Mockito.mock(ServiceProvider.class); - originalServiceProvider= Bootstrap.init(empty); - Bootstrap.init(originalServiceProvider); - testServiceProvider = new TestServiceProvider(); - } - - /** - * Restores the default ServiceProvider. - */ - @AfterMethod - public void restore() { - testServiceProvider.clearServices(); - Bootstrap.init(originalServiceProvider); - } - - protected final void initTestServiceProvider() { - Bootstrap.init(testServiceProvider); - } - - protected final void initOriginalServiceProvider() { - Bootstrap.init(originalServiceProvider); - } - - /** - * Registers a SPI service so that it is accessible via {@link Bootstrap#getService(Class)} when using {@link #testServiceProvider}. - * @param serviceType The SPI type. - * @param service The SPI instance. - */ - protected final void registerService(Class serviceType, T service) { - testServiceProvider.registerService(serviceType, service); - } - - class TestServiceProvider implements ServiceProvider { - - private final Map, List> services = new HashMap<>(); - - @Override - public int getPriority() { - return 0; - } - - @Override - public List getServices(Class serviceType) { - return (List) services.get(serviceType); - } - - @Override - public T getService(Class serviceType) { - List servicesOfType = getServices(serviceType); - if(servicesOfType==null||servicesOfType.isEmpty()) { - return null; - } else { - return servicesOfType.get(0); - } - } - - public void registerService(Class serviceType, T service) { - List servicesOfType = (List) services.get(serviceType); - if(servicesOfType==null) { - servicesOfType = new ArrayList<>(); - services.put(serviceType, servicesOfType); - } - servicesOfType.add(service); - } - - public void clearServices() { - services.clear(); - } - } -} diff --git a/src/test/java/javax/money/AbstractQueryTest.java b/src/test/java/javax/money/AbstractQueryTest.java deleted file mode 100644 index 106ed1403..000000000 --- a/src/test/java/javax/money/AbstractQueryTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import java.util.List; - -import static org.testng.Assert.*; - -/** - * Test class for {@link javax.money.AbstractQuery} and {@link javax.money.AbstractQueryBuilder}. - */ -@SuppressWarnings({"unchecked", "rawtypes"}) -public class AbstractQueryTest { - - - private AbstractQueryBuilder createBuilder() { - return new AbstractQueryBuilder() { - @Override - public AbstractQuery build() { - return new AbstractQuery(this) { - private static final long serialVersionUID = 7131918476096875127L; - }; - } - }; - } - - - @Test - public void testGetProviders() throws Exception { - AbstractQueryBuilder b = createBuilder(); - b.setProviderNames("1", "2", "3"); - AbstractQuery query = b.build(); - assertNotNull(query); - List providers = query.getProviderNames(); - assertNotNull(providers); - assertTrue(providers.size() == 3); - assertTrue(providers.contains("1")); - assertTrue(providers.contains("2")); - assertTrue(providers.contains("3")); - } - - @Test - public void testGetTargetType() throws Exception { - AbstractQueryBuilder b = createBuilder(); - b.setTargetType(String.class); - AbstractQuery query = b.build(); - assertEquals(query.getTargetType(), String.class); - } - -} \ No newline at end of file diff --git a/src/test/java/javax/money/CurrencyContextBuilderTest.java b/src/test/java/javax/money/CurrencyContextBuilderTest.java deleted file mode 100644 index 733107967..000000000 --- a/src/test/java/javax/money/CurrencyContextBuilderTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import static org.testng.Assert.*; - -public class CurrencyContextBuilderTest { - - @Test - public void testOf() throws Exception { - CurrencyContext ctx = CurrencyContextBuilder.of("prov").build(); - assertNotNull(ctx); - assertEquals(ctx.getProviderName(), "prov"); - CurrencyContext ctx2 = CurrencyContextBuilder.of(ctx).build(); - assertNotNull(ctx2); - assertEquals(ctx2.getProviderName(), "prov"); - } -} \ No newline at end of file diff --git a/src/test/java/javax/money/CurrencyQueryBuilderTest.java b/src/test/java/javax/money/CurrencyQueryBuilderTest.java deleted file mode 100644 index 1df21c1be..000000000 --- a/src/test/java/javax/money/CurrencyQueryBuilderTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import static org.testng.Assert.assertEquals; - -import java.util.Collection; -import java.util.Iterator; - -import org.testng.annotations.Test; - -/** - * Test for {@link CurrencyQueryBuilder}. - * - * @author Philippe Marschall - */ -public class CurrencyQueryBuilderTest { - - /** - * Test for {@link CurrencyQueryBuilder#setCurrencyCodes(String...)}. - */ - @Test - public void setNumericCodesString() { - CurrencyQuery query = CurrencyQueryBuilder.of().setCurrencyCodes("CHF", "EUR").build(); - - Collection currencyCodes = query.getCurrencyCodes(); - assertEquals(2, currencyCodes.size()); - Iterator iterator = currencyCodes.iterator(); - assertEquals("CHF", iterator.next()); - assertEquals("EUR", iterator.next()); - } - - /** - * Test for {@link CurrencyQueryBuilder#setNumericCodes(int...)}. - */ - @Test - public void setNumericCodesInt() { - CurrencyQuery query = CurrencyQueryBuilder.of().setNumericCodes(756, 978).build(); - - Collection numericCodes = query.getNumericCodes(); - assertEquals(2, numericCodes.size()); - Iterator iterator = numericCodes.iterator(); - assertEquals(Integer.valueOf(756), iterator.next()); - assertEquals(Integer.valueOf(978), iterator.next()); - } - - @Test - public void testOf_CurrencyQuery() { - CurrencyQuery query = CurrencyQueryBuilder.of().setNumericCodes(756, 978).build(); - assertEquals(CurrencyQueryBuilder.of(query).build(), query); - - } - -} diff --git a/src/test/java/javax/money/DummyAmount.java b/src/test/java/javax/money/DummyAmount.java deleted file mode 100644 index 8e1216c89..000000000 --- a/src/test/java/javax/money/DummyAmount.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.math.MathContext; -import java.util.Objects; - -/** - * Amount pseudo (non functional) implementation, for testing only. - * - * @author Anatole Tresch - */ -public final class DummyAmount implements MonetaryAmount { - - private static final CurrencyContext DUMMY_CURRENCYCONTEXT = CurrencyContextBuilder.of("dummy").build(); - - private final int signum; - private final MonetaryContext monetaryContext; - - public DummyAmount(final int signum, MonetaryContext monetaryContext) { - this.signum = signum; - this.monetaryContext = monetaryContext; - } - - @Override - public CurrencyUnit getCurrency() { - return new CurrencyUnit() { - @Override - public String getCurrencyCode() { - return "DMY"; - } - - @Override - public int getNumericCode() { - return 0; - } - - @Override - public int getDefaultFractionDigits() { - return 2; - } - - @Override - public CurrencyContext getContext() { - return DUMMY_CURRENCYCONTEXT; - } - - @Override - public int compareTo(CurrencyUnit o) { - return 0; - } - }; - } - - @Override - public MonetaryContext getContext() { - return monetaryContext; - } - - @Override - public NumberValue getNumber() { - return new NumberValue() { - - /** - * serialVersionUID. - */ - private static final long serialVersionUID = 1L; - - @Override - public int getPrecision() { - return 0; - } - - @Override - public long getAmountFractionNumerator() { - return 0; - } - - @Override - public long getAmountFractionDenominator() { - return 0; - } - - @Override - public int getScale() { - - return 0; - } - - @Override - public int intValue() { - return 0; - } - - @Override - public int intValueExact() { - return 0; - } - - @Override - public long longValue() { - return 0; - } - - @Override - public long longValueExact() { - return 0; - } - - @Override - public double doubleValue() { - return 0; - } - - @Override - public double doubleValueExact() { - return 0; - } - - @Override - public T numberValue(Class numberType) { - return null; - } - - @Override - public NumberValue round(MathContext mathContext) { - return this; - } - - @Override - public T numberValueExact(Class numberType) { - return null; - } - - @Override - public float floatValue() { - return 0; - } - - @Override - public Class getNumberType() { - return Void.class; - } - }; - } - - - @Override - public boolean isGreaterThan(MonetaryAmount amount) { - - return false; - } - - @Override - public boolean isGreaterThanOrEqualTo(MonetaryAmount amt) { - - return false; - } - - @Override - public boolean isLessThan(MonetaryAmount amt) { - - return false; - } - - @Override - public boolean isLessThanOrEqualTo(MonetaryAmount amt) { - - return false; - } - - @Override - public boolean isEqualTo(MonetaryAmount amount) { - - return false; - } - - @Override - public int signum() { - - return signum; - } - - @Override - public DummyAmount add(MonetaryAmount amount) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount subtract(MonetaryAmount amount) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount multiply(long multiplicand) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount multiply(double multiplicand) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount multiply(Number multiplicand) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount divide(long amount) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount divide(double amount) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount divide(Number amount) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount remainder(long amount) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount remainder(double amount) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount remainder(Number amount) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount[] divideAndRemainder(long amount) { - return new DummyAmount[]{new DummyAmountBuilder().create(), new DummyAmountBuilder().create()}; - } - - @Override - public DummyAmount[] divideAndRemainder(double amount) { - return new DummyAmount[]{new DummyAmountBuilder().create(), new DummyAmountBuilder().create()}; - } - - @Override - public DummyAmount[] divideAndRemainder(Number amount) { - return new DummyAmount[]{new DummyAmountBuilder().create(), new DummyAmountBuilder().create()}; - } - - @Override - public DummyAmount divideToIntegralValue(long divisor) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount divideToIntegralValue(double divisor) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount divideToIntegralValue(Number divisor) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount scaleByPowerOfTen(int power) { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount abs() { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount negate() { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount plus() { - - return new DummyAmountBuilder().create(); - } - - @Override - public DummyAmount stripTrailingZeros() { - - return new DummyAmountBuilder().create(); - } - - @Override - public MonetaryAmountFactory getFactory() { - return new DummyAmountBuilder(); - } - - @Override - public int compareTo(MonetaryAmount o) { - Objects.requireNonNull(o); - return 0; - } -} diff --git a/src/test/java/javax/money/DummyAmountBuilder.java b/src/test/java/javax/money/DummyAmountBuilder.java deleted file mode 100644 index 42a173742..000000000 --- a/src/test/java/javax/money/DummyAmountBuilder.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -/** - * Dummy amount factory only used for testing of the {@link Monetary} singleton's delegation - * logic. - * - * @author Anatole Tresch - */ -public final class DummyAmountBuilder implements MonetaryAmountFactory { - /** - * The {@link MonetaryContext} used. - */ - private static final MonetaryContext DUMMY_CONTEXT = MonetaryContextBuilder.of(MonetaryAmount.class) - .set("dummy", true) - .build(); - - /** - * The signum for the created DummyAmount. - */ - private int signum = 0; - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#getAmountType() - */ - @Override - public Class getAmountType() { - return DummyAmount.class; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#getDefaultMonetaryContext() - */ - @Override - public MonetaryContext getDefaultMonetaryContext() { - return DUMMY_CONTEXT; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#getMaximalMonetaryContext() - */ - @Override - public MonetaryContext getMaximalMonetaryContext() { - return DUMMY_CONTEXT; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#setCurrency(java.lang.String) - */ - @Override - public DummyAmountBuilder setCurrency(String currencyCode) { - return this; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#setCurrency(javax.money.CurrencyUnit) - */ - @Override - public DummyAmountBuilder setCurrency(CurrencyUnit currency) { - return this; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#of() - */ - @Override - public DummyAmount create() { - return new DummyAmount(signum, DUMMY_CONTEXT); - } - - /** - * Sets the signum for the DummyAmount to be created. - * - * @param signum the signum value to set - */ - public DummyAmountBuilder setSignum(final int signum) { - this.signum = signum; - return this; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#setNumber(double) - */ - @Override - public DummyAmountBuilder setNumber(double number) { - return this; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#setNumber(long) - */ - @Override - public DummyAmountBuilder setNumber(long number) { - return this; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#setNumber(java.lang.Number) - */ - @Override - public DummyAmountBuilder setNumber(Number number) { - return this; - } - - @Override - public NumberValue getMaxNumber() { - return null; - } - - @Override - public NumberValue getMinNumber() { - return null; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#setContext(javax.money.MonetaryContext) - */ - @Override - public DummyAmountBuilder setContext(MonetaryContext monetaryContext) { - return this; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#setAmount(javax.money.MonetaryAmount) - */ - @Override - public DummyAmountBuilder setAmount(MonetaryAmount amount) { - return this; - } - -} diff --git a/src/test/java/javax/money/DummyAmountFactoryProvider.java b/src/test/java/javax/money/DummyAmountFactoryProvider.java deleted file mode 100644 index 9674c2b46..000000000 --- a/src/test/java/javax/money/DummyAmountFactoryProvider.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import javax.money.spi.MonetaryAmountFactoryProviderSpi; - -/** - * Dummy amount factory only used for testing of the {@link Monetary} singleton's delegation - * logic. - * - * @author Anatole Tresch - */ -public final class DummyAmountFactoryProvider implements MonetaryAmountFactoryProviderSpi { - - /** - * The {@link MonetaryContext} used. - */ - private static final MonetaryContext DUMMY_CONTEXT = MonetaryContextBuilder.of(MonetaryAmount.class) - .set("dummy", true) - .build(); - - @Override - public MonetaryAmountFactory createMonetaryAmountFactory() { - return new DummyAmountBuilder(); - } - - @Override - public Class getAmountType() { - return DummyAmount.class; - } - - @Override - public MonetaryContext getMaximalMonetaryContext() { - return DUMMY_CONTEXT; - } - - /* - * (non-Javadoc) - * @see javax.money.MonetaryAmountFactory#getQueryInclusionPolicy() - */ - @Override - public QueryInclusionPolicy getQueryInclusionPolicy() { - return QueryInclusionPolicy.ALWAYS; - } - - @Override - public MonetaryContext getDefaultMonetaryContext() { - return DUMMY_CONTEXT; - } - -} diff --git a/src/test/java/javax/money/MonetaryAmountFactoryQueryTest.java b/src/test/java/javax/money/MonetaryAmountFactoryQueryTest.java deleted file mode 100644 index 27eedb936..000000000 --- a/src/test/java/javax/money/MonetaryAmountFactoryQueryTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; - -/** - * @author Anatole Tresch - */ -public class MonetaryAmountFactoryQueryTest { - - private static final int MAX_SCALE = 5; - private static final int PRECISION = 3; - private static final boolean FIXED_SCALE = true; - - private final MonetaryAmountFactoryQuery query = new MonetaryAmountFactoryQuery(MonetaryAmountFactoryQueryBuilder - .of() - .setMaxScale(MAX_SCALE) - .setPrecision(PRECISION) - .setFixedScale(FIXED_SCALE)); - - /** - * Test method for - * {@link MonetaryAmountFactoryQuery#getMaxScale()}. - */ - @Test - public void testGetMaxScaleReturnsConfiguredValue() throws Exception { - //when - final int retVal = query.getMaxScale(); - - //then - assertEquals(retVal, MAX_SCALE); - - } - - /** - * Test method for - * {@link MonetaryAmountFactoryQuery#getPrecision()}. - */ - @Test - public void testGetPrecision() throws Exception { - //when - final int retVal = query.getPrecision(); - - //then - assertEquals(retVal, PRECISION); - } - - /** - * Test method for - * {@link MonetaryAmountFactoryQuery#isFixedScale()}. - */ - @Test - public void testGetFixedScale() throws Exception { - //when - final boolean retVal = query.isFixedScale(); - - //then - assertEquals(retVal, FIXED_SCALE); - } - - /** - * Test method for - * {@link MonetaryAmountFactoryQuery#toBuilder()}. - */ - @Test - public void testToBuilder() throws Exception { - //when - final MonetaryAmountFactoryQueryBuilder builder = query.toBuilder(); - - //then - assertNotNull(builder); - } -} diff --git a/src/test/java/javax/money/MonetaryAmountTest.java b/src/test/java/javax/money/MonetaryAmountTest.java deleted file mode 100644 index 652f988d4..000000000 --- a/src/test/java/javax/money/MonetaryAmountTest.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertSame; -import static org.testng.Assert.assertTrue; - -public class MonetaryAmountTest { - - - /** - * Test method for - * {@link MonetaryAmount#query(MonetaryQuery)}. - */ - @Test - public void testQuery() throws Exception { - - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().create(); - - //when - final MonetaryAmount retVal = monetaryAmount.query(amount -> amount); - - //then - assertSame(retVal, monetaryAmount); - } - - /** - * Test method for - * {@link MonetaryAmount#with(MonetaryOperator)}. - */ - @Test - public void testWith() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().create(); - - //when - final MonetaryAmount retVal = monetaryAmount.with(amount -> amount); - - //then - assertSame(retVal, monetaryAmount); - } - - /** - * Test method for - * {@link MonetaryAmount#isNegative()}}. - */ - @Test - public void testIsNegativeWithNegativeSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(-1).create(); - - //when - final boolean retVal = monetaryAmount.isNegative(); - - //then - assertTrue(retVal); - } - - /** - * Test method for - * {@link MonetaryAmount#isNegative()}}. - */ - @Test - public void testIsNegativeWithZeroSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(0).create(); - - //when - final boolean retVal = monetaryAmount.isNegative(); - - //then - assertFalse(retVal); - } - - /** - * Test method for - * {@link MonetaryAmount#isNegative()}}. - */ - @Test - public void testIsNegativeWithPositiveSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(1).create(); - - //when - final boolean retVal = monetaryAmount.isNegative(); - - //then - assertFalse(retVal); - } - - - /** - * Test method for - * {@link javax.money.MonetaryAmount#isNegativeOrZero()}}. - */ - @Test - public void testIsNegativeOrZeroWithNegativeSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(-1).create(); - - //when - final boolean retVal = monetaryAmount.isNegativeOrZero(); - - //then - assertTrue(retVal); - } - - /** - * Test method for - * {@link javax.money.MonetaryAmount#isNegativeOrZero()}}. - */ - @Test - public void testIsNegativeOrZeroWithZeroSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(0).create(); - - //when - final boolean retVal = monetaryAmount.isNegativeOrZero(); - - //then - assertTrue(retVal); - } - - /** - * Test method for - * {@link javax.money.MonetaryAmount#isNegativeOrZero()}}. - */ - @Test - public void testIsNegativeOrZeroWithPositiveSignumReturnsFalse() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(1).create(); - - //when - final boolean retVal = monetaryAmount.isNegativeOrZero(); - - //then - assertFalse(retVal); - } - - /** - * Test method for - * {@link MonetaryAmount#isPositive()}. - */ - @Test - public void testIsPositiveWithPositiveSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(1).create(); - - //when - final boolean retVal = monetaryAmount.isPositive(); - - //then - assertTrue(retVal); - } - - /** - * Test method for - * {@link MonetaryAmount#isPositive()}. - */ - @Test - public void testIsPositiveWithZeroSignumReturnsFalse() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(0).create(); - - //when - final boolean retVal = monetaryAmount.isPositive(); - - //then - assertFalse(retVal); - } - - /** - * Test method for - * {@link MonetaryAmount#isPositive()}. - */ - @Test - public void testIsPositiveWithNegativeSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(-1).create(); - - //when - final boolean retVal = monetaryAmount.isPositive(); - - //then - assertFalse(retVal); - } - - - /** - * Test method for - * {@link javax.money.MonetaryAmount#isPositiveOrZero()}. - */ - @Test - public void testIsPositiveOrZeroWithPositiveSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(1).create(); - - //when - final boolean retVal = monetaryAmount.isPositiveOrZero(); - - //then - assertTrue(retVal); - } - - /** - * Test method for - * {@link javax.money.MonetaryAmount#isPositiveOrZero()}. - */ - @Test - public void testIsPositiveOrZeroWithZeroSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(0).create(); - - //when - final boolean retVal = monetaryAmount.isPositiveOrZero(); - - //then - assertTrue(retVal); - } - - /** - * Test method for - * {@link javax.money.MonetaryAmount#isPositiveOrZero()}. - */ - @Test - public void testIsPositiveOrZeroWithNegativeSignumReturnsFalse() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(-1).create(); - - //when - final boolean retVal = monetaryAmount.isPositiveOrZero(); - - //then - assertFalse(retVal); - } - - /** - * Test method for - * {@link javax.money.MonetaryAmount#isZero()}. - */ - @Test - public void testIsZeroWithPositiveSignumReturnsFalse() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(1).create(); - - //when - final boolean retVal = monetaryAmount.isZero(); - - //then - assertFalse(retVal); - } - - /** - * Test method for - * {@link javax.money.MonetaryAmount#isZero()}. - */ - @Test - public void testIsZeroWithZeroSignumReturnsTrue() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(0).create(); - - //when - final boolean retVal = monetaryAmount.isZero(); - - //then - assertTrue(retVal); - } - - /** - * Test method for - * {@link javax.money.MonetaryAmount#isZero()}. - */ - @Test - public void testIsZeroWithNegativeSignumReturnsFalse() throws Exception { - //given - final MonetaryAmount monetaryAmount = new DummyAmountBuilder().setSignum(-1).create(); - - //when - final boolean retVal = monetaryAmount.isZero(); - - //then - assertFalse(retVal); - } -} diff --git a/src/test/java/javax/money/MonetaryAmountsTest.java b/src/test/java/javax/money/MonetaryAmountsTest.java deleted file mode 100644 index 2fbecb07a..000000000 --- a/src/test/java/javax/money/MonetaryAmountsTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import static org.testng.Assert.*; - -import org.testng.annotations.Test; - -import java.util.Collection; - -/** - * @author Anatole - */ -public class MonetaryAmountsTest { - - /** - * Test method for - * {@link javax.money.Monetary#getAmountFactory(java.lang.Class)}. - */ - @Test - public void testGetFactory() { - assertNotNull(Monetary.getDefaultAmountFactory()); - assertNotNull(Monetary.getAmountFactory(DummyAmount.class)); - assertTrue(Monetary.getDefaultAmountFactory().getClass() == - Monetary.getAmountFactory(DummyAmount.class).getClass()); - } - - /** - * Test method for {@link javax.money.Monetary#getAmountTypes()}. - */ - @Test - public void testGetTypes() { - assertNotNull(Monetary.getAmountTypes()); - assertTrue(Monetary.getAmountTypes().size() == 1); - assertTrue(Monetary.getAmountTypes().contains(DummyAmount.class)); - } - - /** - * Test method for - * {@link javax.money.Monetary#getDefaultAmountType()}. - */ - @Test - public void testGetDefaultAmountFactory() { - assertNotNull(Monetary.getDefaultAmountFactory()); - assertEquals(DummyAmountBuilder.class, Monetary.getDefaultAmountFactory().getClass()); - } - - /** - * Test method for - * {@link Monetary#getAmountFactories()}. - */ - @Test - public void testGetAmountFactories() { - Collection> factories = Monetary.getAmountFactories(); - assertNotNull(factories); - assertFalse(factories.isEmpty()); - } - - /** - * Test method for - * {@link Monetary#getDefaultAmountType()}. - */ - @Test - public void testGetDefaultAmountType() { - Class type = Monetary.getDefaultAmountType(); - assertNotNull(type); - assertEquals(type, DummyAmount.class); - } - - /** - * Test method for - * {@link Monetary#getAmountFactory(MonetaryAmountFactoryQuery)}. - */ - @Test - public void testGetAmountFactory_Query() { - @SuppressWarnings("rawtypes") - MonetaryAmountFactory f = Monetary.getAmountFactory(MonetaryAmountFactoryQueryBuilder.of() - .setTargetType(DummyAmount.class).build()); - assertNotNull(f); - assertEquals(f.getClass(), DummyAmountBuilder.class); - - } - - /** - * Test method for - * {@link Monetary#getAmountFactories(MonetaryAmountFactoryQuery)}. - */ - @Test - public void testGetAmountFactories_Query() { - Collection> factories = Monetary. - getAmountFactories(MonetaryAmountFactoryQueryBuilder.of() - .setTargetType(DummyAmount.class).build()); - assertNotNull(factories); - assertTrue(factories.size() == 1); - factories = Monetary. - getAmountFactories(MonetaryAmountFactoryQueryBuilder.of() - .setProviderName("gigigig2").build()); - assertNotNull(factories); - assertTrue(factories.isEmpty()); - } - - /** - * Test method for - * {@link Monetary#getAmountFactories(MonetaryAmountFactoryQuery)}. - */ - @Test - public void testIsAvailable_Query() { - assertTrue(Monetary. - isAvailable(MonetaryAmountFactoryQueryBuilder.of() - .setTargetType(DummyAmount.class).build())); - assertFalse(Monetary. - isAvailable(MonetaryAmountFactoryQueryBuilder.of() - .setProviderName("gigigig2").build())); - } - -} diff --git a/src/test/java/javax/money/MonetaryContextTest.java b/src/test/java/javax/money/MonetaryContextTest.java deleted file mode 100644 index 524645217..000000000 --- a/src/test/java/javax/money/MonetaryContextTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.testng.Assert.*; - -/** - * Tests for {@link javax.money.MonetaryContext}. - */ -public class MonetaryContextTest { - - @Test - public void testGetPrecision() throws Exception { - MonetaryContext ctx = MonetaryContextBuilder.of(MonetaryAmount.class).setPrecision(299).build(); - assertTrue(ctx.getPrecision() == 299); - } - - @Test - public void testIsFixedScale() throws Exception { - MonetaryContext ctx = MonetaryContextBuilder.of(MonetaryAmount.class).setFixedScale(true).build(); - assertTrue(ctx.isFixedScale()); - } - - @Test - public void testGetMaxScale() throws Exception { - MonetaryContext ctx = MonetaryContextBuilder.of(MonetaryAmount.class).setMaxScale(122).build(); - assertTrue(ctx.getMaxScale() == 122); - } - - @Test - public void testGetAmountTypeExplicit() throws Exception { - MonetaryContext ctx = MonetaryContextBuilder.of(MonetaryAmount.class).setAmountType(DummyAmount.class).build(); - assertTrue(ctx.getAmountType() == DummyAmount.class); - } - - @Test - public void testOf_MonetaryContext() throws Exception { - MonetaryContext ctx = MonetaryContextBuilder.of(MonetaryAmount.class).setAmountType(DummyAmount.class).build(); - assertEquals(ctx, MonetaryContextBuilder.of(ctx).build()); - } - - @Test - public void testGetAmountType() throws Exception { - MonetaryContext ctx = MonetaryContextBuilder.of(MonetaryAmount.class).setMaxScale(122).build(); - assertEquals(ctx.getAmountType(), MonetaryAmount.class); - //noinspection ClassMayBeInterface - abstract class TestAmount implements MonetaryAmount { - } - ctx = MonetaryContextBuilder.of(TestAmount.class).build(); - assertEquals(ctx.getAmountType(), TestAmount.class); - } - - @Test - public void testHashCode() throws Exception { - List contexts = new ArrayList<>(); - contexts.add(MonetaryContextBuilder.of(MonetaryAmount.class).setMaxScale(122).build()); - contexts.add(MonetaryContextBuilder.of(MonetaryAmount.class).setPrecision(299).build()); - contexts.add(MonetaryContextBuilder.of(MonetaryAmount.class).setFixedScale(true).build()); - Set hashCodes = new HashSet<>(); - contexts.forEach(ctx -> hashCodes.add(ctx.hashCode())); - // Check we have 5 distinct hash codes... - assertTrue(hashCodes.size() == 3); - } - - @Test - public void testEquals() throws Exception { - List contexts = new ArrayList<>(); - contexts.add(MonetaryContextBuilder.of(MonetaryAmount.class).setMaxScale(122).build()); - contexts.add(MonetaryContextBuilder.of(MonetaryAmount.class).setPrecision(299).build()); - contexts.add(MonetaryContextBuilder.of(MonetaryAmount.class).setFixedScale(true).build()); - Set checkContexts = new HashSet<>(); - for (MonetaryContext ctx : contexts) { - checkContexts.add(ctx); - checkContexts.add(ctx); - } - // Check we have 5 distinct hash codes... - assertTrue(checkContexts.size() == 3); - } - - @Test - public void testToString() throws Exception { - //noinspection ClassMayBeInterface - abstract class TestAmount implements MonetaryAmount { - } - MonetaryContext ctx = - MonetaryContextBuilder.of(TestAmount.class).setFixedScale(true).setMaxScale(111).setPrecision(200) - .set("myKey", "myValue").set("TEST").build(); - assertNotNull(ctx.toString()); - assertTrue(ctx.toString().contains("111")); - assertTrue(ctx.toString().contains("200")); - assertTrue(ctx.toString().contains("TEST")); - assertTrue(ctx.toString().contains("myKey")); - assertTrue(ctx.toString().contains("myValue")); - assertTrue(ctx.toString().contains("String")); - assertTrue(ctx.toString().contains("maxScale")); - assertTrue(ctx.toString().contains("precision")); - assertTrue(ctx.toString().contains("fixedScale")); - assertTrue(ctx.toString().contains("TestAmount")); - assertTrue(ctx.toString().contains("amountType")); - assertTrue(ctx.toString().contains("MonetaryContext")); - } -} diff --git a/src/test/java/javax/money/MonetaryDynamicServiceProviderTest.java b/src/test/java/javax/money/MonetaryDynamicServiceProviderTest.java deleted file mode 100644 index 38878e078..000000000 --- a/src/test/java/javax/money/MonetaryDynamicServiceProviderTest.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; - -import javax.money.internal.DefaultMonetaryAmountsSingletonQuerySpi; -import javax.money.internal.DefaultMonetaryAmountsSingletonSpi; -import javax.money.spi.Bootstrap; -import javax.money.spi.MonetaryAmountsSingletonQuerySpi; -import javax.money.spi.MonetaryAmountsSingletonSpi; -import javax.money.spi.MonetaryCurrenciesSingletonSpi; -import javax.money.spi.MonetaryRoundingsSingletonSpi; -import javax.money.spi.RoundingProviderSpi; -import javax.money.spi.ServiceProvider; - -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.testng.annotations.Test; - -/** - * Test to ensure that singleton SPIs used by {@link Monetary} handle substitution of {@link ServiceProvider} to use when - * calling {@link Bootstrap#init(javax.money.spi.ServiceProvider)}. (e.g. in an OSGI environment) - * @author Matthias Hanisch - * - */ -public class MonetaryDynamicServiceProviderTest extends AbstractDynamicServiceProviderTest { - - - /** - * Default SPI: {@link DefaultMonetaryCurrenciesSingletonSpi} supports currencies test1 and test2. - * Dynamic SPI: Mock supporting currencies test1 and test3. - * Testing following steps: - *
    - *
  • use default SPI
  • - *
  • currency test1 available
  • - *
  • currency test2 available
  • - *
  • currency test3 not available
  • - *
  • use dynamic SPI
  • - *
  • currency test1 available
  • - *
  • currency test2 not available
  • - *
  • currency test3 available
  • - *
  • use default SPI
  • - *
  • currency test1 available
  • - *
  • currency test2 available
  • - *
  • currency test3 not available
  • - *
- * - */ - @Test - public void testMonetaryCurrenciesSingletonSpi() { - // DefaultMonetaryCurrenciesSingletonSpi is used - assertCurrencyAvailable("test1"); - assertCurrencyAvailable("test2"); - assertCurrencyMissing("test3"); - MonetaryCurrenciesSingletonSpi mockSingleton = mock(MonetaryCurrenciesSingletonSpi.class); - registerService(MonetaryCurrenciesSingletonSpi.class, mockSingleton); - doAnswer(new Answer() { - private final List supportedCurrencies = Arrays.asList("test1","test3"); - @Override - public CurrencyUnit answer(InvocationOnMock invocation) - throws Throwable { - String currencyCode =(String)invocation.getArguments()[0]; - if(supportedCurrencies.contains(currencyCode)) { - return new TestCurrency(currencyCode, 1,2); - } - throw new UnknownCurrencyException(currencyCode); - } - }).when(mockSingleton).getCurrency(anyString()); - initTestServiceProvider(); - // DynamicMonetaryCurrenciesSingletonSpi is used - assertCurrencyAvailable("test1"); - assertCurrencyMissing("test2"); - assertCurrencyAvailable("test3"); - initOriginalServiceProvider(); - // DefaultMonetaryCurrenciesSingletonSpi is used again - assertCurrencyAvailable("test1"); - assertCurrencyAvailable("test2"); - assertCurrencyMissing("test3"); - } - - /** - * Default SPI: {@link DefaultMonetaryAmountsSingletonSpi} supports a {@link MonetaryAmountFactory} creating instances of DummyAmount. - * Dynamic SPI: Mock supporting a {@link MonetaryAmountFactory} creating a mocked {@link MonetaryAmount} - * Testing following steps: - *
    - *
  • use default SPI
  • - *
  • created MonetaryAmount should be a DummyAmount
  • - *
  • use dynamic SPI
  • - *
  • created MonetaryAmount should match the mocked Amount
  • - *
  • use default SPI
  • - *
  • created MonetaryAmount should be a DummyAmount
  • - *
- */ - @Test - public void testMonetaryAmountsSingletonSpi() { - assertTrue(Monetary.getDefaultAmountFactory().create()instanceof DummyAmount); - MonetaryAmountsSingletonSpi mockSingleton = mock(MonetaryAmountsSingletonSpi.class); - MonetaryAmountFactory mockFactory = mock(MonetaryAmountFactory.class); - MonetaryAmount mockAmount = mock(MonetaryAmount.class); - doReturn(mockFactory).when(mockSingleton).getDefaultAmountFactory(); - doReturn(mockAmount).when(mockFactory).create(); - registerService(MonetaryAmountsSingletonSpi.class, mockSingleton); - initTestServiceProvider(); - assertFalse(Monetary.getDefaultAmountFactory().create()instanceof DummyAmount); - assertEquals(Monetary.getDefaultAmountFactory().create(), mockAmount); - initOriginalServiceProvider(); - assertTrue(Monetary.getDefaultAmountFactory().create()instanceof DummyAmount); - } - - /** - * Default SPI: {@link DefaultMonetaryAmountsSingletonQuerySpi} supports {@link MonetaryAmountFactoryQuery} for DummyAmount. - * Dynamic SPI: Mock not supporting {@link MonetaryAmountFactoryQuery} for none MonetaryMount at all. - * Testing following steps: - *
    - *
  • use default SPI
  • - *
  • query for DummyAmount should be true
  • - *
  • use dynamic SPI
  • - *
  • query for DummyAmount should be false
  • - *
  • use default SPI
  • - *
  • query for DummyAmount should be true
  • - *
- */ - @Test - public void testMonetaryAmountsSingletonQuerySpi() { - MonetaryAmountFactoryQuery query = MonetaryAmountFactoryQueryBuilder.of() - .setTargetType(DummyAmount.class).build(); - assertTrue(Monetary.isAvailable(query)); - MonetaryAmountsSingletonQuerySpi mock= mock(MonetaryAmountsSingletonQuerySpi.class); - doReturn(Boolean.FALSE).when(mock).isAvailable(any(MonetaryAmountFactoryQuery.class)); - registerService(MonetaryAmountsSingletonQuerySpi.class, mock); - initTestServiceProvider(); - assertFalse(Monetary.isAvailable(query)); - initOriginalServiceProvider(); - assertTrue(Monetary.isAvailable(query)); - } - - /** - * Default SPI: {@link DefaultMonetaryRoundingsSingletonSpi} uses {@link RoundingProviderSpi} supporting two rounding names. - * Dynamic SPI: Mock supporting one rounding name. - * Testing following steps: - *
    - *
  • use default SPI
  • - *
  • number of rounding names should be two
  • - *
  • use dynamic SPI
  • - *
  • number of rounding names should be one
  • - *
  • use default SPI
  • - *
  • number of rounding names should be two
  • - *
- */ - @Test - public void testMonetaryRoundingsSingletonSpi() { - assertEquals(Monetary.getRoundingNames().size(),2); - MonetaryRoundingsSingletonSpi mock = mock(MonetaryRoundingsSingletonSpi.class); - doReturn(new HashSet<>(Collections.singletonList("dummyRounding"))).when(mock).getRoundingNames(); - registerService(MonetaryRoundingsSingletonSpi.class, mock); - initTestServiceProvider(); - assertEquals(Monetary.getRoundingNames().size(),1); - initOriginalServiceProvider(); - assertEquals(Monetary.getRoundingNames().size(),2); - } - - private void assertCurrencyAvailable(String currency) { - CurrencyUnit cur = Monetary.getCurrency(currency); - assertNotNull(cur); - } - - private void assertCurrencyMissing(String currency) { - try { - CurrencyUnit cur = Monetary.getCurrency(currency); - fail(String.format("currency %s should not be available, but got %s", currency, cur)); - } catch(UnknownCurrencyException ex) { - ex.printStackTrace(); - // expected - } - } - - -} diff --git a/src/test/java/javax/money/MonetaryExceptionTest.java b/src/test/java/javax/money/MonetaryExceptionTest.java deleted file mode 100644 index 16f8a038c..000000000 --- a/src/test/java/javax/money/MonetaryExceptionTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import static org.testng.Assert.*; - -/** - * Tests for {@link javax.money.MonetaryException}. - */ -public class MonetaryExceptionTest{ - @Test - public void testGetMessage() throws Exception{ - MonetaryException e = new MonetaryException("message1"); - assertNotNull(e.getMessage()); - assertTrue(e.getMessage().contains("message1")); - assertNull(e.getCause()); - } - - @Test - public void testGetCause() throws Exception{ - MonetaryException e = new MonetaryException("message1", new Exception("Test")); - assertNotNull(e.getMessage()); - assertTrue(e.getMessage().contains("message1")); - assertNotNull(e.getCause()); - assertEquals(e.getCause().getMessage(), "Test"); - } -} diff --git a/src/test/java/javax/money/MonetaryRoundingsTest.java b/src/test/java/javax/money/MonetaryRoundingsTest.java deleted file mode 100644 index 39f834c00..000000000 --- a/src/test/java/javax/money/MonetaryRoundingsTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import java.util.Collection; -import java.util.List; -import java.util.Set; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; - -public class MonetaryRoundingsTest { - - @Test - public void testMonetaryRoundingsGetRoundingCurrencyUnit() { - MonetaryOperator op = Monetary.getRounding(Monetary.getCurrency("test1")); - assertNotNull(op); - } - - @Test - public void testMonetaryRoundingsGetRoundingQueryWithLongTS() { - MonetaryOperator op = Monetary.getRounding( - RoundingQueryBuilder.of().setCurrency(Monetary.getCurrency("test1")).set("timestamp", 200L) - .build()); - assertNotNull(op); - } - - @Test - public void testMonetaryRoundingsGetRoundingQueryAny() { - Collection roundings = Monetary.getRoundings(RoundingQueryBuilder.of().build()); - assertNotNull(roundings); - assertFalse(roundings.isEmpty()); - } - - @Test - public void testMonetaryRoundingsGetDefaultRounding() { - MonetaryOperator op = Monetary.getDefaultRounding(); - assertNotNull(op); - } - - @Test - public void testMonetaryRoundingsGetRoundingWithId() { - MonetaryOperator op = Monetary.getRounding("custom1"); - assertNotNull(op); - } - - @Test - public void testIsRoundingsAvailable() { - assertTrue(Monetary.isRoundingAvailable("custom1")); - assertFalse(Monetary.isRoundingAvailable("foo")); - } - - @Test - public void testIsRoundingsAvailable_CurrencyUnit() { - assertFalse(Monetary.isRoundingAvailable(TestCurrency.of("CHF"), "foo")); - assertTrue(Monetary.isRoundingAvailable(TestCurrency.of("CHF"))); - } - - @Test - public void testIsRoundingsAvailable_Query() { - assertTrue(Monetary.isRoundingAvailable( - RoundingQueryBuilder.of().setCurrency(TestCurrency.of("CHF")).set("timestamp", 200L) - .build())); - assertFalse(Monetary.isRoundingAvailable( - RoundingQueryBuilder.of().setCurrency(TestCurrency.of("CHF")).setProviderName("foo") - .build())); - } - - @Test - public void testGetDefaultProviderChain() { - List chain = Monetary.getDefaultRoundingProviderChain(); - assertNotNull(chain); - assertFalse(chain.isEmpty()); - } - - @Test - public void testMonetaryRoundingsGetCustomRoundingIds() { - Set ids = Monetary.getRoundingNames(); - assertNotNull(ids); - assertTrue(ids.size() == 2); - } - - @Test - public void testMonetaryRoundingsGetProviderNames() { - Set names = Monetary.getRoundingProviderNames(); - assertNotNull(names); - assertTrue(names.size() == 1); - } -} diff --git a/src/test/java/javax/money/MonetaryTest.java b/src/test/java/javax/money/MonetaryTest.java deleted file mode 100644 index b61c00d8b..000000000 --- a/src/test/java/javax/money/MonetaryTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.Set; - -import static org.testng.Assert.*; - -/** - * Tests for the {@link Monetary} class. - * - * @author Anatole Tresch - */ -public class MonetaryTest { - - @Test - public void testgetCurrencyString() { - CurrencyUnit cur = Monetary.getCurrency("test1"); - assertNotNull(cur); - assertEquals(cur.getCurrencyCode(), "test1"); - assertEquals(cur.getNumericCode(), 1); - assertEquals(cur.getDefaultFractionDigits(), 2); - } - - @Test - public void testIsAvailableString() { - assertTrue(Monetary.isCurrencyAvailable("test1")); - assertFalse(Monetary.isCurrencyAvailable("akjshakjshajsgdgsdgsdg")); - } - - @Test - public void testIsAvailableLocale() { - assertFalse(Monetary.isCurrencyAvailable(Locale.CHINA)); - assertTrue(Monetary.isCurrencyAvailable(new Locale("", "TEST1L"))); - } - - @Test(expectedExceptions = UnknownCurrencyException.class) - public void testgetCurrencyString_NA() { - Monetary.getCurrency("testGetInstanceCurrency_NA"); - } - - @Test - public void testgetCurrencyLocale() { - Collection curs = Monetary.getCurrencies(new Locale("", "TEST1L")); - assertNotNull(curs); - assertEquals(curs.size(), 1); - CurrencyUnit cur = curs.iterator().next(); - assertEquals(cur.getCurrencyCode(), "TEST1L"); - assertEquals(cur.getNumericCode(), 1); - assertEquals(cur.getDefaultFractionDigits(), 2); - } - - @Test - public void testGetCurrencies_Providers() { - Collection curs = Monetary.getCurrencies("test"); - assertNotNull(curs); - } - - @Test(expectedExceptions = MonetaryException.class) - public void testGetCurrency_CurrencyQuery() { - CurrencyUnit cur = Monetary.getCurrency( - CurrencyQueryBuilder.of().build()); - assertNull(cur); - cur = Monetary.getCurrency( - CurrencyQueryBuilder.of().setCurrencyCodes("test1").build()); - assertNotNull(cur); - } - - - @Test - public void testGetCurrencies_CurrencyQuery() { - Collection currencies = Monetary.getCurrencies( - CurrencyQueryBuilder.of().build() - ); - assertNotNull(currencies); - } - - @Test - public void testGetProviderNames() { - Set chain = Monetary.getCurrencyProviderNames(); - assertNotNull(chain); - } - - @Test - public void testGetDefaultProviderChain() { - List chain = Monetary.getDefaultCurrencyProviderChain(); - assertNotNull(chain); - } - - @Test - public void testgetCurrencyLocale_Empty() { - Collection curs = Monetary.getCurrencies(Locale.CHINA); - assertNotNull(curs); - assertTrue(curs.isEmpty()); - curs = Monetary.getCurrencies(new Locale("", "sdsdsd")); - assertNotNull(curs); - assertTrue(curs.isEmpty()); - } - - @Test(expectedExceptions = UnknownCurrencyException.class) - public void testgetCurrencyString_Error() { - CurrencyUnit cur = Monetary.getCurrency("error"); - assertNull(cur); - cur = Monetary.getCurrency("invalid"); - assertNull(cur); - } - - -} diff --git a/src/test/java/javax/money/NumberValueTest.java b/src/test/java/javax/money/NumberValueTest.java deleted file mode 100644 index 3b9d80d98..000000000 --- a/src/test/java/javax/money/NumberValueTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import javax.money.convert.TestNumberValue; - -import static org.testng.Assert.*; - -public class NumberValueTest { - - @Test - public void testCompareTo() throws Exception { - NumberValue nv1a = new TestNumberValue(1); - NumberValue nv2 = new TestNumberValue(2); - NumberValue nv1b = new TestNumberValue(1); - - assertEquals(nv1a.compareTo(nv2), -1); - assertEquals(nv2.compareTo(nv1a), 1); - assertEquals(nv1a.compareTo(nv1b), 0); - assertEquals(nv2.compareTo(nv2), 0); - } -} \ No newline at end of file diff --git a/src/test/java/javax/money/RoundingContextTest.java b/src/test/java/javax/money/RoundingContextTest.java deleted file mode 100644 index 1f7d2163f..000000000 --- a/src/test/java/javax/money/RoundingContextTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import static org.testng.Assert.*; - -public class RoundingContextTest { - - @Test - public void testGetRoundingName() throws Exception { - RoundingContext ctx = RoundingContextBuilder.of("prov", "r1").build(); - assertNotNull(ctx); - assertEquals(ctx.getRoundingName(), "r1"); - } - - @Test - public void testGetCurrency() throws Exception { - CurrencyUnit cu = TestCurrency.of("CHF"); - RoundingContext ctx = RoundingContextBuilder.of("prov", "r1"). - setCurrency(cu).build(); - assertNotNull(ctx); - assertEquals(ctx.getCurrency(), cu); - } - - @Test - public void testToBuilder() throws Exception { - CurrencyUnit cu = TestCurrency.of("CHF"); - RoundingContext ctx = RoundingContextBuilder.of("prov1", "rounding2") - .setCurrency(cu).build(); - RoundingContextBuilder b = ctx.toBuilder(); - assertNotNull(b); - assertEquals(b.build(), ctx); - } -} \ No newline at end of file diff --git a/src/test/java/javax/money/RoundingQueryBuilderTest.java b/src/test/java/javax/money/RoundingQueryBuilderTest.java deleted file mode 100644 index 3cd239d55..000000000 --- a/src/test/java/javax/money/RoundingQueryBuilderTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import static org.testng.Assert.*; - -public class RoundingQueryBuilderTest { - - @Test - public void testSetScale() throws Exception { - RoundingQueryBuilder b = RoundingQueryBuilder.of().setScale(6); - assertEquals(b.build().getScale(), Integer.valueOf(6)); - } - - @Test - public void testOf() throws Exception { - RoundingQueryBuilder b1 = RoundingQueryBuilder.of().setScale(6); - RoundingQueryBuilder b2 = RoundingQueryBuilder.of(b1.build()); - assertEquals(b1.build().getScale(), Integer.valueOf(6)); - assertEquals(b2.build().getScale(), Integer.valueOf(6)); - } -} \ No newline at end of file diff --git a/src/test/java/javax/money/TestCurrency.java b/src/test/java/javax/money/TestCurrency.java deleted file mode 100644 index ab7f41dab..000000000 --- a/src/test/java/javax/money/TestCurrency.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import java.io.Serializable; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Adapter that implements the new {@link javax.money.CurrencyUnit} interface using the - * JDK's {@link java.util.Currency}. - * - * @author Anatole Tresch - * @author Werner Keil - * @version 0.5 - */ -public final class TestCurrency implements CurrencyUnit, Serializable, Comparable { - - private static final CurrencyContext CONTEXT = CurrencyContextBuilder.of("test-only").build(); - - /** - * The predefined name space for ISO 4217 currencies, similar to - * {@link java.util.Currency}. - */ - private static final String ISO_NAMESPACE = "ISO-4217"; - - /** - * serialVersionUID. - */ - private static final long serialVersionUID = -2523936311372374236L; - - /** - * currency code for this currency. - */ - private final String currencyCode; - /** - * numeric code, or -1. - */ - private final int numericCode; - /** - * fraction digits, or -1. - */ - private final int defaultFractionDigits; - - private static final Map CACHED = new ConcurrentHashMap<>(); - - /** - * Private constructor. - */ - TestCurrency(String code, int numCode, int fractionDigits) { - this.currencyCode = code; - this.numericCode = numCode; - this.defaultFractionDigits = fractionDigits; - } - - public static CurrencyUnit of(Currency currency) { - String key = ISO_NAMESPACE + ':' + currency.getCurrencyCode(); - CurrencyUnit cachedItem = CACHED.get(key); - if (Objects.isNull(cachedItem)) { - cachedItem = new JDKCurrencyAdapter(currency); - CACHED.put(key, cachedItem); - } - return cachedItem; - } - - - public static CurrencyUnit of(String currencyCode) { - CurrencyUnit cu = CACHED.get(currencyCode); - if (Objects.isNull(cu)) { - Currency cur = Currency.getInstance(currencyCode); - if (Objects.nonNull(cur)) { - return of(cur); - } - } - return cu; - } - - @Override - public String getCurrencyCode() { - return currencyCode; - } - - @Override - public int getNumericCode() { - return numericCode; - } - - @Override - public int getDefaultFractionDigits() { - return defaultFractionDigits; - } - - @Override - public CurrencyContext getContext() { - return CONTEXT; - } - - public int getCashRounding() { - throw new UnsupportedOperationException("Not supported yet."); // To - // change - // body - // of - // generated - // methods, - // choose - // Tools - // | - // Templates. - } - - @Override - public int compareTo(CurrencyUnit currency) { - Objects.requireNonNull(currency); - return getCurrencyCode().compareTo(currency.getCurrencyCode()); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return currencyCode; - } - - public static final class Builder { - /** - * currency code for this currency. - */ - private String currencyCode; - /** - * numeric code, or -1. - */ - private int numericCode = -1; - /** - * fraction digits, or -1. - */ - private int defaultFractionDigits = -1; - - public Builder() { - } - - public Builder(String currencyCode) { - withCurrencyCode(currencyCode); - } - - public Builder withCurrencyCode(String currencyCode) { - - if (Objects.isNull(currencyCode)) { - throw new IllegalArgumentException("currencyCode may not be null."); - } - this.currencyCode = currencyCode; - return this; - } - - public Builder withDefaultFractionDigits(int defaultFractionDigits) { - if (defaultFractionDigits < -1) { - throw new IllegalArgumentException("Invalid value for defaultFractionDigits: " + defaultFractionDigits); - } - this.defaultFractionDigits = defaultFractionDigits; - return this; - } - - public Builder withNumericCode(int numericCode) { - if (numericCode < -1) { - throw new IllegalArgumentException("Invalid value for numericCode: " + numericCode); - } - this.numericCode = numericCode; - return this; - } - - - public CurrencyUnit build() { - return build(true); - } - - public CurrencyUnit build(boolean cache) { - if (Objects.isNull(currencyCode) || currencyCode.isEmpty()) { - throw new IllegalStateException("Can not of TestCurrencyUnit."); - } - if (cache) { - String key = currencyCode; - CurrencyUnit current = CACHED.get(key); - if (Objects.isNull(current)) { - current = new TestCurrency(currencyCode, numericCode, defaultFractionDigits); - CACHED.put(key, current); - } - return current; - } - return new TestCurrency(currencyCode, numericCode, defaultFractionDigits); - } - } - - /** - * Adapter that implements the new {@link javax.money.CurrencyUnit} interface using the - * JDK's {@link java.util.Currency}. - *

- * This adapter will be removed in the final platform implementation. - * - * @author Anatole Tresch - * @author Werner Keil - */ - private final static class JDKCurrencyAdapter implements CurrencyUnit, Serializable, Comparable { - - private static final CurrencyContext JDK_CONTEXT = CurrencyContextBuilder.of(Currency.class.getName()).build(); - - /** - * serialVersionUID. - */ - private static final long serialVersionUID = -2523936311372374236L; - - /** - * ISO 4217 currency code for this currency. - * - * @serial - */ - private final Currency currency; - - /** - * Private constructor. - * - * @param currency the JDK currency, not null. - */ - private JDKCurrencyAdapter(Currency currency) { - if (Objects.isNull(currency)) { - throw new IllegalArgumentException("Currency required."); - } - this.currency = currency; - } - - @Override - public int compareTo(CurrencyUnit currency) { - Objects.requireNonNull(currency); - int compare = getCurrencyCode().compareTo(currency.getCurrencyCode()); - if (compare == 0) { - compare = getCurrencyCode().compareTo(currency.getCurrencyCode()); - } - return compare; - } - - @Override - public String getCurrencyCode() { - return this.currency.getCurrencyCode(); - } - - @Override - public int getNumericCode() { - return this.currency.getNumericCode(); - } - - @Override - public int getDefaultFractionDigits() { - return this.currency.getDefaultFractionDigits(); - } - - @Override - public CurrencyContext getContext() { - return JDK_CONTEXT; - } - - @Override - public String toString() { - return this.currency.toString(); - } - - } - - // it be used and if so, - // consider changing it to a pattern similar as getAvailableCurrencies() - // (including the type Set, unless Collection provides value) - public static Collection getAllMatching(String expression) { - return Collections.emptySet(); - } - -} diff --git a/src/test/java/javax/money/TestCurrencyProvider.java b/src/test/java/javax/money/TestCurrencyProvider.java deleted file mode 100644 index 9668ca4ec..000000000 --- a/src/test/java/javax/money/TestCurrencyProvider.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import javax.money.spi.CurrencyProviderSpi; -import java.util.*; - -public final class TestCurrencyProvider implements CurrencyProviderSpi { - - @Override - public Set getCurrencies(CurrencyQuery currencyQuery) { - Set result = new HashSet<>(); - if (!currencyQuery.getCurrencyCodes().isEmpty()) { - for (String currencyCode : currencyQuery.getCurrencyCodes()) { - switch (currencyCode) { - case "test1": - result.add(new TestCurrency("test1", 1, 2)); - break; - case "test2": - result.add(new TestCurrency("test2", 1, 2)); - break; - case "error": - throw new IllegalArgumentException("error encountered!"); - case "invalid": - result.add(new TestCurrency("invalid2", 1, 2)); - break; - default: - break; - } - } - return result; - } - if (!currencyQuery.getCountries().isEmpty()) { - for (Locale country : currencyQuery.getCountries()) { - if ("TEST1L".equals(country.getCountry())) { - result.add(new TestCurrency("TEST1L", 1, 2)); - } else if (Locale.CHINA.equals(country)) { - throw new IllegalArgumentException("CHINA error encountered!"); - } else if (Locale.CHINESE.equals(country)) { - result.add(new TestCurrency("invalid2", 1, 2)); - } - } - return result; - } - return Collections.emptySet(); - } - - @Override - public boolean isCurrencyAvailable(CurrencyQuery context) { - Collection currencyCodes = context.getCurrencyCodes(); - for (String currencyCode : currencyCodes) { - switch (currencyCode) { - case "test1": - case "error": - case "invalid": - return true; - } - } - Collection countries = context.getCountries(); - for (Locale country : countries) { - if ("TEST1L".equals(country.getCountry())) { - return true; - } else if (Locale.CHINA.equals(country)) { - return true; - } else if (Locale.CHINESE.equals(country)) { - return true; - } - } - return false; - } - - - @Override - public String getProviderName() { - return "test"; - } - - - private static final class TestCurrency implements CurrencyUnit { - - private final String code; - private final int numCode; - private final int digits; - private static final CurrencyContext CONTEXT = CurrencyContextBuilder.of("TestCurrencyProvider").build(); - - TestCurrency(String code, int numCode, int digits) { - this.code = code; - this.numCode = numCode; - this.digits = digits; - } - - @Override - public String getCurrencyCode() { - return code; - } - - @Override - public int getNumericCode() { - return numCode; - } - - @Override - public int getDefaultFractionDigits() { - return digits; - } - - @Override - public CurrencyContext getContext() { - return CONTEXT; - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return Objects.hashCode(code); - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof TestCurrency) { - TestCurrency other = (TestCurrency) obj; - return Objects.equals(code, other.code); - } - return false; - } - - @Override - public int compareTo(CurrencyUnit o) { - Objects.requireNonNull(o); - return getCurrencyCode().compareTo(o.getCurrencyCode()); - } - } - -} diff --git a/src/test/java/javax/money/TestRoundingProvider.java b/src/test/java/javax/money/TestRoundingProvider.java deleted file mode 100644 index 9523acbbe..000000000 --- a/src/test/java/javax/money/TestRoundingProvider.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import javax.money.spi.RoundingProviderSpi; -import java.util.HashSet; -import java.util.Set; - -public final class TestRoundingProvider implements RoundingProviderSpi { - - @Override - public MonetaryRounding getRounding(RoundingQuery roundingQuery) { - if ("foo".equals(roundingQuery.getRoundingName())) { - return null; - } - if (roundingQuery.getRoundingName() != null) { - return getCustomRounding(roundingQuery.getRoundingName()); - } - if (roundingQuery.getCurrency() != null) { - return getCustomRounding(roundingQuery.getCurrency().getCurrencyCode()); - } - return getCustomRounding("test"); - } - - private MonetaryRounding getCustomRounding(final String customRoundingId) { - return new MonetaryRounding() { - - private final RoundingContext CTX = - RoundingContextBuilder.of("TestRoundingProvider", customRoundingId).build(); - - @Override - public RoundingContext getRoundingContext() { - return CTX; - } - - @Override - public MonetaryAmount apply(MonetaryAmount monetaryAmount) { - switch (customRoundingId) { - case "custom1": - return monetaryAmount.multiply(2); - case "custom2": - return monetaryAmount.multiply(3); - default: - return monetaryAmount; - } - } - }; - } - - - @Override - public Set getRoundingNames() { - Set result = new HashSet<>(); - result.add("custom1"); - result.add("custom2"); - return result; - } - -} diff --git a/src/test/java/javax/money/UnknownCurrencyExceptionTest.java b/src/test/java/javax/money/UnknownCurrencyExceptionTest.java deleted file mode 100644 index 2b56fa439..000000000 --- a/src/test/java/javax/money/UnknownCurrencyExceptionTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money; - -import org.testng.annotations.Test; - -import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static org.testng.Assert.*; - -/** - * Tests for {@link javax.money.UnknownCurrencyException}. - */ -public class UnknownCurrencyExceptionTest { - - private static final Logger LOGGER = Logger.getLogger(UnknownCurrencyExceptionTest.class.getName()); - @Test - public void testGetCurrencyCode() throws Exception{ - UnknownCurrencyException e = new UnknownCurrencyException("GGG"); - assertEquals("GGG", e.getCurrencyCode()); - assertNull(e.getLocale()); - assertTrue(e.toString().contains("GGG")); - assertTrue(e.toString().contains("UnknownCurrencyException")); - } - - @Test - public void testGetLocale() throws Exception{ - UnknownCurrencyException e = new UnknownCurrencyException(Locale.CANADA_FRENCH); - assertEquals(Locale.CANADA_FRENCH, e.getLocale()); - assertNull(e.getCurrencyCode()); - LOGGER.log(Level.INFO, e.getMessage(), e); - assertTrue(e.toString().contains(Locale.CANADA_FRENCH.toString())); - assertTrue(e.toString().contains("UnknownCurrencyException")); - } - -} diff --git a/src/test/java/javax/money/convert/ConversionContextTest.java b/src/test/java/javax/money/convert/ConversionContextTest.java deleted file mode 100644 index f62dd595c..000000000 --- a/src/test/java/javax/money/convert/ConversionContextTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - - -import static org.testng.Assert.assertEquals; - -import org.testng.annotations.Test; - -/** - * Tests for {@link ConversionContext}. - */ -public class ConversionContextTest { - @Test - public void testGetRateType() throws Exception { - ConversionContext ctx = ConversionContextBuilder.of().setRateType(RateType.DEFERRED).build(); - assertEquals(RateType.DEFERRED, ctx.getRateType()); - } - - @Test - public void testGetProvider() throws Exception { - ConversionContext ctx = ConversionContextBuilder.of().setProviderName("myprov").build(); - assertEquals("myprov", ctx.getProviderName()); - } - - @Test - public void testToBuilder() throws Exception { - ConversionContext ctx = ConversionContextBuilder.of().setProviderName("myprov").build(); - assertEquals(ctx, ctx.toBuilder().build()); - } - - @Test - public void testOf() throws Exception { - ConversionContext ctx = ConversionContext.of(); - ConversionContext ctx2 = ConversionContext.of(); - assertEquals(ctx, ctx2); - } - - @Test - public void testOf1() throws Exception { - ConversionContext ctx = ConversionContext.of(RateType.REALTIME); - ConversionContext ctx2 = ConversionContext.of(RateType.REALTIME); - assertEquals(ctx, ctx2); - assertEquals(RateType.REALTIME, ctx.getRateType()); - } - - @Test - public void testOf2() throws Exception { - ConversionContext ctx = ConversionContext.of("prov", RateType.REALTIME); - ConversionContext ctx2 = ConversionContext.of("prov", RateType.REALTIME); - assertEquals(ctx, ctx2); - assertEquals(RateType.REALTIME, ctx.getRateType()); - assertEquals("prov", ctx.getProviderName()); - } -} diff --git a/src/test/java/javax/money/convert/CurrencyConversionExceptionTest.java b/src/test/java/javax/money/convert/CurrencyConversionExceptionTest.java deleted file mode 100644 index 1134cf93f..000000000 --- a/src/test/java/javax/money/convert/CurrencyConversionExceptionTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.CurrencyUnit; -import javax.money.TestCurrency; - -import org.testng.Assert; -import org.testng.annotations.Test; - -public class CurrencyConversionExceptionTest { - - private static final ConversionContext CONTEXT100 = - ConversionContextBuilder.of().setProviderName("test").set("timestampMillis", 100L).build(); - - @Test - public void testCurrencyConversionExceptionCurrencyUnitCurrencyUnitContext() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit term = TestCurrency.of("EUR"); - CurrencyConversionException ex = new CurrencyConversionException(base, term, CONTEXT100); - Assert.assertEquals(null, ex.getCause()); - Assert.assertEquals(base, ex.getBaseCurrency()); - Assert.assertEquals(term, ex.getTermCurrency()); - Assert.assertEquals(CONTEXT100, ex.getConversionContext()); - Assert.assertEquals("Cannot convert CHF into EUR", ex.getMessage()); - } - - @Test - public void testCurrencyConversionExceptionCurrencyUnitCurrencyUnitLongStringContextStringThrowable() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit term = TestCurrency.of("EUR"); - Exception cause = new Exception("cause"); - CurrencyConversionException ex = new CurrencyConversionException(base, term, CONTEXT100, "blabla", cause); - Assert.assertEquals(cause, ex.getCause()); - Assert.assertEquals(base, ex.getBaseCurrency()); - Assert.assertEquals(term, ex.getTermCurrency()); - Assert.assertEquals(CONTEXT100, ex.getConversionContext()); - Assert.assertEquals("Cannot convert CHF into EUR: blabla", ex.getMessage()); - } - - @Test - public void testToString() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit term = TestCurrency.of("EUR"); - Exception cause = new Exception("cause"); - CurrencyConversionException ex = new CurrencyConversionException(base, term, CONTEXT100, "blabla", cause); - String toString = ex.toString(); - Assert.assertNotNull(toString); - Assert.assertTrue(toString.contains("CurrencyConversionException")); - Assert.assertTrue(toString.contains("base=CHF")); - Assert.assertTrue(toString.contains("term=EUR")); - Assert.assertTrue(toString.contains("conversionContext=ConversionContext")); - Assert.assertTrue(toString.contains("provider=test")); - Assert.assertTrue(toString.contains("Cannot convert CHF into EUR")); - Assert.assertTrue(toString.contains("blabla")); - } - -} diff --git a/src/test/java/javax/money/convert/DefaultExchangeRate.java b/src/test/java/javax/money/convert/DefaultExchangeRate.java deleted file mode 100644 index e8cb3b523..000000000 --- a/src/test/java/javax/money/convert/DefaultExchangeRate.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.CurrencyUnit; -import javax.money.NumberValue; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -/** - * This class models an exchange rate, which defines the factor the numeric value of a baseCurrency amount in some - * currency - * 'A' must be multiplied - * to get the corresponding amount in the terminating currency 'B'. Hereby - *

    - *
  • an exchange rate always models one rate from a baseCurrency (source) to a termCurrency - * (target) {@link javax.money.CurrencyUnit}.
  • - *
  • an exchange rate is always bound to a rate type, which typically matches - * the data source of the conversion data, e.g. different credit card providers - * may use different rates for the same conversion.
  • - *
  • an exchange rate may restrict its validity. In most of the use cases a - * rates' validity will be well defined, but it is also possible that the data - * provider is not able to support the rate's validity, leaving it undefined-
  • - *
  • an exchange rate has a provider, which is responsible for defining the - * rate. A provider hereby may be, but must not be the same as the rate's data - * source.
  • - *
  • an exchange rate can be a direct rate, where its factor is - * represented by a single conversion step. Or it can model a derived - * rate, where multiple conversion steps are required to define the overall - * baseCurrency/termCurrency conversion. In case of derived rates the chained rates define the - * overall factor, by multiplying the individual chain rate factors. Of course, - * this also requires that each subsequent rate's baseCurrency currency in the chain - * does match the previous termCurrency currency (and vice versa):
  • - *
  • Whereas the factor should be directly implied by the format rate chain - * for derived rates, this is obviously not the case for the validity range, - * since rates can have a undefined validity range. Nevertheless in many cases - * also the validity range can (but must not) be derived from the rate chain.
  • - *
  • Finally a conversion rate is always unidirectional. There might be cases - * where the reciprocal value of {@link #factor} matches the correct reverse - * rate. But in most use cases the reverse rate either has a different rate (not - * equal to the reciprocal value), or might not be defined at all. Therefore for - * reversing a ExchangeRate one must access an {@link ExchangeRateProvider} and - * query for the reverse rate.
  • - *
- *

- * The class also implements {@link Comparable} to allow sorting of multiple - * exchange rates using the following sorting order; - *

    - *
  • Exchange rate type
  • - *
  • Exchange rate provider
  • - *
  • baseCurrency currency
  • - *
  • termCurrency currency
  • - *
- *

- * Finally ExchangeRate is modeled as an immutable and thread safe type. Also - * exchange rates are {@link java.io.Serializable}, hereby serializing in the following - * form and order: - *

    - *
  • The baseCurrency {@link javax.money.CurrencyUnit} - *
  • The target {@link javax.money.CurrencyUnit} - *
  • The factor (NumberValue) - *
  • The {@link ConversionContext} - *
  • The rate chain - *
- * - * @author Werner Keil - * @author Anatole Tresch - * @see Wikipedia: - * Exchange Rate (Quotations) - */ -public final class DefaultExchangeRate implements ExchangeRate, Serializable, Comparable { - - /** - * serialVersionUID. - */ - private static final long serialVersionUID = 5077295306570465837L; - /** - * The baseCurrency currency. - */ - private final CurrencyUnit baseCurrency; - /** - * The terminating currency. - */ - private final CurrencyUnit termCurrency; - /** - * The conversion factor. - */ - private final NumberValue factor; - /** - * The {@link ConversionContext} - */ - private final ConversionContext conversionContext; - /** - * The full chain, at least one instance long. - */ - private final List chain = new ArrayList<>(); - - - /** - * Creates a new instance with a custom chain of exchange rate type, e.g. or - * creating derived rates. - * - * @param builder The Builder, never {@code null}. - */ - private DefaultExchangeRate(Builder builder) { - Objects.requireNonNull(builder.baseCurrency, "baseCurrency may not be null."); - Objects.requireNonNull(builder.termCurrency, "termCurrency may not be null."); - Objects.requireNonNull(builder.factor, "factor may not be null."); - Objects.requireNonNull(builder.conversionContext, "exchangeRateType may not be null."); - this.baseCurrency = builder.baseCurrency; - this.termCurrency = builder.termCurrency; - this.factor = builder.factor; - this.conversionContext = builder.conversionContext; - - setExchangeRateChain(builder.rateChain); - } - - /** - * Internal method to set the rate chain, which also ensure that the chain - * passed, when not null, contains valid elements. - * - * @param chain the chain to set. - */ - private void setExchangeRateChain(List chain) { - this.chain.clear(); - if (Objects.isNull(chain) || chain.isEmpty()) { - this.chain.add(this); - } else { - for (ExchangeRate rate : chain) { - if (Objects.isNull(rate)) { - throw new IllegalArgumentException("Chain element can not be null."); - } - } - this.chain.addAll(chain); - } - } - - /** - * Access the {@link ConversionContext} of {@link ExchangeRate}. - * - * @return the conversion context, never null. - */ - @Override - public ConversionContext getContext() { - return this.conversionContext; - } - - /** - * Get the baseCurrency (source) {@link javax.money.CurrencyUnit}. - * - * @return the baseCurrency {@link javax.money.CurrencyUnit}. - */ - @Override - public CurrencyUnit getBaseCurrency() { - return this.baseCurrency; - } - - /** - * Get the termCurrency (target) {@link javax.money.CurrencyUnit}. - * - * @return the termCurrency {@link javax.money.CurrencyUnit}. - */ - @Override - public CurrencyUnit getCurrency() { - return this.termCurrency; - } - - /** - * Access the rate's bid factor. - * - * @return the bid factor for this exchange rate, or {@code null}. - */ - @Override - public NumberValue getFactor() { - return this.factor; - } - - /** - * Access the chain of exchange rates. - * - * @return the chain of rates, in case of a derived rate, this may be - * several instances. For a direct exchange rate, this equals to - * new ExchangeRate[]{this}. - */ - @Override - public List getExchangeRateChain() { - return this.chain; - } - - /** - * Allows to evaluate if this exchange rate is a derived exchange rate. - * Derived exchange rates are defined by an ordered list of child conversions - * with intermediate steps, whereas a direct conversion is possible in one - * steps. - *

- * This method always returns {@code true}, if the chain contains more than - * one rate. Direct rates, have also a chain, but with exact one rate. - * - * @return true, if the exchange rate is derived. - */ - @Override - public boolean isDerived() { - return this.chain.size() > 1; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - @Override - public int compareTo(ExchangeRate o) { - Objects.requireNonNull(o); - int compare = this.getBaseCurrency().getCurrencyCode().compareTo(o.getBaseCurrency().getCurrencyCode()); - if (compare == 0) { - compare = this.getCurrency().getCurrencyCode().compareTo(o.getCurrency().getCurrencyCode()); - } - if (compare == 0) { - compare = this.getContext().getProviderName().compareTo(o.getContext().getProviderName()); - } - return compare; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "ExchangeRate [baseCurrency=" + baseCurrency + ", factor=" + factor + ", conversionContext=" + - conversionContext + "]"; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - // Numerically equal factors should produce the same hash code, so hash a normalized - // version of the factor rather than the NumberValue object. - BigDecimal normalizedFactor = factor.numberValue(BigDecimal.class).stripTrailingZeros(); - - // The exchange rate chain includes a reference to "this" if the caller doesn't explicitly - // set a chain in the builder, so we can't naively hash the chain or we'll get infinite - // recursion. - int chainHash = 0; - for (ExchangeRate chainedRate : chain) { - if (chainedRate == this) { - // Use a constant to represent the presence of this object in the chain. - chainHash = Objects.hash(chainHash, "this"); - } else { - chainHash = Objects.hash(chainHash, chainedRate); - } - } - return Objects.hash(baseCurrency, conversionContext, normalizedFactor, termCurrency, chainHash); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - DefaultExchangeRate other = (DefaultExchangeRate) obj; - return Objects.equals(baseCurrency, other.baseCurrency) && - Objects.equals(conversionContext, other.conversionContext) && - factor.compareTo(other.factor) == 0 && - Objects.equals(termCurrency, other.termCurrency); - } - - /** - * Builder for creating new instances of {@link ExchangeRate}. Note that - * instances of this class are not thread-safe. - * - * @author Anatole Tresch - * @author Werner Keil - */ - public static class Builder { - - /** - * The {@link ConversionContext}. - */ - private ConversionContext conversionContext; - /** - * The baseCurrency (source) currency. - */ - private CurrencyUnit baseCurrency; - /** - * The termCurrency (target) currency. - */ - private CurrencyUnit termCurrency; - /** - * The conversion factor. - */ - private NumberValue factor; - /** - * The chain of involved rates. - */ - private List rateChain = new ArrayList<>(); - - /** - * Sets the exchange rate type - * - * @param rateType the {@link RateType} contained - */ - public Builder(String provider, RateType rateType) { - this(ConversionContext.of(provider, rateType)); - } - - /** - * Sets the exchange rate type - * - * @param context the {@link ConversionContext} to be applied - */ - public Builder(ConversionContext context) { - setContext(context); - } - - /** - * Sets the baseCurrency {@link javax.money.CurrencyUnit} - * - * @param base to baseCurrency (source) {@link javax.money.CurrencyUnit} to be applied - * @return the builder instance - */ - public Builder setBaseCurrency(CurrencyUnit base) { - this.baseCurrency = base; - return this; - } - - /** - * Sets the terminating (target) {@link javax.money.CurrencyUnit} - * - * @param term to terminating {@link javax.money.CurrencyUnit} to be applied - * @return the builder instance - */ - public Builder setTermCurrency(CurrencyUnit term) { - this.termCurrency = term; - return this; - } - - /** - * Sets the {@link ExchangeRate} chain. - * - * @param exchangeRates the {@link ExchangeRate} chain to be applied - * @return the builder instance - */ - public Builder setRateChain(ExchangeRate... exchangeRates) { - this.rateChain.clear(); - if (Objects.nonNull(exchangeRates)) { - this.rateChain.addAll(Arrays.asList(exchangeRates.clone())); - } - return this; - } - - /** - * Sets the {@link ExchangeRate} chain. - * - * @param exchangeRates the {@link ExchangeRate} chain to be applied - * @return the builder instance - */ - public Builder setRateChain(List exchangeRates) { - this.rateChain.clear(); - if (Objects.nonNull(exchangeRates)) { - this.rateChain.addAll(exchangeRates); - } - return this; - } - - - /** - * Sets the conversion factor, as the factor - * {@code baseCurrency * factor = target}. - * - * @param factor the factor. - * @return The builder instance. - */ - public Builder setFactor(NumberValue factor) { - this.factor = factor; - return this; - } - - /** - * Sets the provider to be applied. - * - * @param conversionContext the {@link ConversionContext}, not null. - * @return The builder. - */ - public Builder setContext(ConversionContext conversionContext) { - Objects.requireNonNull(conversionContext); - this.conversionContext = conversionContext; - return this; - } - - /** - * Builds a new instance of {@link ExchangeRate}. - * - * @return a new instance of {@link ExchangeRate}. - * @throws IllegalArgumentException if the rate could not be built. - */ - public DefaultExchangeRate build() { - return new DefaultExchangeRate(this); - } - - /** - * Initialize the {@link Builder} with an {@link ExchangeRate}. This is - * useful for creating a new rate, reusing some properties from an - * existing one. - * - * @param rate the baseCurrency rate - * @return the Builder, for chaining. - */ - public Builder setRate(ExchangeRate rate) { - this.baseCurrency = rate.getBaseCurrency(); - this.termCurrency = rate.getCurrency(); - this.conversionContext = rate.getContext(); - this.factor = rate.getFactor(); - this.rateChain = rate.getExchangeRateChain(); - this.termCurrency = rate.getCurrency(); - return this; - } - } - - /** - * Create a {@link Builder} based on the current rate instance. - * - * @return a new {@link Builder}, never {@code null}. - */ - public Builder toBuilder() { - return new Builder(getContext()).setBaseCurrency(getBaseCurrency()).setTermCurrency(getCurrency()) - .setFactor(getFactor()) - .setRateChain(getExchangeRateChain()); - } -} diff --git a/src/test/java/javax/money/convert/ExchangeRateProviderTest.java b/src/test/java/javax/money/convert/ExchangeRateProviderTest.java deleted file mode 100644 index 96e12c78f..000000000 --- a/src/test/java/javax/money/convert/ExchangeRateProviderTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; - -import java.math.BigDecimal; - -import org.testng.annotations.Test; - -/** - * Test for {@link ExchangeRateProvider}. - * - * @author Philippe Marschall - */ -public class ExchangeRateProviderTest { - - /** - * Test for {@link ExchangeRateProvider#getCurrencyConversion(String)}. - */ - @Test - public void testGetCurrencyConversion() { - ExchangeRateProvider prov = MonetaryConversions - .getExchangeRateProvider(); - CurrencyConversion conversion = prov.getCurrencyConversion("test1"); - assertNotNull(conversion); - assertEquals("test1", conversion.getCurrency().getCurrencyCode()); - } - - /** - * Test for {@link ExchangeRateProvider#getExchangeRate(String, String)}. - */ - @Test - public void testGetExchangeRate() { - ExchangeRateProvider prov = MonetaryConversions - .getExchangeRateProvider(); - ExchangeRate exchangeRate = prov.getExchangeRate("test1", "test2"); - assertNotNull(exchangeRate); - assertEquals("test1", exchangeRate.getBaseCurrency().getCurrencyCode()); - assertEquals("test2", exchangeRate.getCurrency().getCurrencyCode()); - assertEquals(new BigDecimal("0.5"), exchangeRate.getFactor().numberValue(BigDecimal.class)); - } - - /** - * Test for {@link ExchangeRateProvider#getReversed(ExchangeRate)}. - */ - @Test - public void testReversed() { - ExchangeRateProvider prov = MonetaryConversions - .getExchangeRateProvider(); - ExchangeRate exchangeRate = prov.getExchangeRate("test1", "test2"); - ExchangeRate reversed = prov.getReversed(exchangeRate); - assertEquals("test2", reversed.getBaseCurrency().getCurrencyCode()); - assertEquals("test1", reversed.getCurrency().getCurrencyCode()); - assertEquals(new BigDecimal("2"), reversed.getFactor().numberValue(BigDecimal.class)); - } - -} diff --git a/src/test/java/javax/money/convert/ExchangeRateTest.java b/src/test/java/javax/money/convert/ExchangeRateTest.java deleted file mode 100644 index 20a876c3f..000000000 --- a/src/test/java/javax/money/convert/ExchangeRateTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - - -import javax.money.CurrencyUnit; -import javax.money.TestCurrency; - -import org.testng.annotations.Test; - -import java.util.Arrays; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -/** - * @author Anatole Tresch - * @author Werner Keil - */ -public class ExchangeRateTest { - - @Test - public void testExchangeRateExchangeRateTypeCurrencyUnitCurrencyUnitNumberString() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit term = TestCurrency.of("EUR"); - ExchangeRate rate = new DefaultExchangeRate.Builder("myProvider", RateType.DEFERRED).setBaseCurrency(base) - .setTermCurrency(term).setFactor(TestNumberValue.of(1.5)).build(); - assertEquals(base, rate.getBaseCurrency()); - assertEquals(term, rate.getCurrency()); - assertTrue(1.5d == rate.getFactor().doubleValue()); - assertEquals(ConversionContext.of("myProvider", RateType.DEFERRED), - rate.getContext()); - assertEquals(Arrays.asList(rate), - rate.getExchangeRateChain()); - } - - @Test - public void testExchangeRateExchangeRateTypeCurrencyUnitCurrencyUnitNumberStringLongLong() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit term = TestCurrency.of("EUR"); - ExchangeRate rate = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(base) - .setTermCurrency(term).setFactor(TestNumberValue.of(1.5)).build(); - assertEquals(base, rate.getBaseCurrency()); - assertEquals(term, rate.getCurrency()); - assertTrue(1.5d == rate.getFactor().doubleValue()); - assertEquals(ConversionContext.of("test", RateType.DEFERRED), - rate.getContext()); - assertEquals(Arrays.asList(rate), - rate.getExchangeRateChain()); - } - - @Test - public void testExchangeRateExchangeRateTypeCurrencyUnitCurrencyUnitNumberStringExchangeRateArray() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit baseTerm = TestCurrency.of("EUR"); - CurrencyUnit term = TestCurrency.of("USD"); - ExchangeRate rate1 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(base) - .setTermCurrency(baseTerm).setFactor(TestNumberValue.of(0.8)).build(); - ExchangeRate rate2 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(baseTerm) - .setTermCurrency(term).setFactor(TestNumberValue.of(1.4)).build(); - - // derived rate - ExchangeRate rate = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(base) - .setTermCurrency(term).setFactor(TestNumberValue.of(0.8 * 1.4)).setRateChain(rate1, rate2).build(); - - assertEquals(base, rate.getBaseCurrency()); - assertEquals(term, rate.getCurrency()); - assertTrue(0.8d * 1.4d == rate.getFactor().doubleValue()); - assertEquals(ConversionContext.of("test", RateType.DEFERRED), - rate.getContext()); - assertEquals(Arrays.asList(rate1, rate2), - rate.getExchangeRateChain()); - } - - @Test - public void testExchangeRateExchangeRateTypeCurrencyUnitCurrencyUnitNumberStringLongLongExchangeRateArray() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit baseTerm = TestCurrency.of("EUR"); - CurrencyUnit term = TestCurrency.of("USD"); - ExchangeRate rate1 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(base) - .setTermCurrency(baseTerm).setFactor(TestNumberValue.of(0.8)).build(); - ExchangeRate rate2 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(baseTerm) - .setTermCurrency(term).setFactor(TestNumberValue.of(1.4)).build(); - - // derived rate - ExchangeRate rate = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(base) - .setTermCurrency(term).setFactor(TestNumberValue.of(0.8 * 1.4)).setRateChain(rate1, rate2).build(); - assertEquals(base, rate.getBaseCurrency()); - assertEquals(term, rate.getCurrency()); - assertTrue(0.8d * 1.4d == rate.getFactor().doubleValue()); - assertEquals(ConversionContext.of("test", RateType.DEFERRED), - rate.getContext()); - assertEquals(Arrays.asList(rate1, rate2), - rate.getExchangeRateChain()); - } - - @Test - public void testToString() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit baseTerm = TestCurrency.of("EUR"); - CurrencyUnit term = TestCurrency.of("USD"); - ExchangeRate rate1 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(base) - .setTermCurrency(baseTerm).setFactor(TestNumberValue.of(0.8)).build(); - ExchangeRate rate2 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(baseTerm) - .setTermCurrency(term).setFactor(TestNumberValue.of(1.4)).build(); - - // derived rate - ExchangeRate rate = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(base) - .setTermCurrency(term).setFactor(TestNumberValue.of(0.8 * 1.4)).setRateChain(rate1, rate2).build(); - String toString = rate.toString(); - assertTrue(toString.contains("ExchangeRate [")); - assertTrue(toString.contains("baseCurrency=CHF, factor=1.1199999999999999, conversionContext=")); - assertTrue(toString.contains("RateType")); - assertTrue(toString.contains("=DEFERRED")); - assertTrue(toString.contains("provider=test")); - } - -} diff --git a/src/test/java/javax/money/convert/ExchangeRate_BuilderTest.java b/src/test/java/javax/money/convert/ExchangeRate_BuilderTest.java deleted file mode 100644 index ac7e54900..000000000 --- a/src/test/java/javax/money/convert/ExchangeRate_BuilderTest.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import org.testng.annotations.Test; - -import javax.money.CurrencyUnit; -import javax.money.TestCurrency; - -import java.math.BigDecimal; -import java.util.Arrays; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertSame; - -/** - * @author Anatole Tresch - * @author Werner Keil - */ -public class ExchangeRate_BuilderTest { - - @Test - public void testWithConversionContext() { - DefaultExchangeRate.Builder b = new DefaultExchangeRate.Builder("test", RateType.DEFERRED); - DefaultExchangeRate.Builder b2 = b.setContext(ConversionContext.of("test", RateType.DEFERRED)); - assertSame(b, b2); - b2 = b.setContext(ConversionContext.of("test2", RateType.DEFERRED)); - assertSame(b, b2); - } - - @Test - public void testGetSetBase() { - DefaultExchangeRate.Builder b = new DefaultExchangeRate.Builder("test", RateType.DEFERRED); - DefaultExchangeRate.Builder b2 = b.setBaseCurrency(TestCurrency.of("CHF")); - assertSame(b, b2); - } - - @Test - public void testGetSetTerm() { - DefaultExchangeRate.Builder b = new DefaultExchangeRate.Builder("test", RateType.DEFERRED); - DefaultExchangeRate.Builder b2 = b.setTermCurrency(TestCurrency.of("CHF")); - assertSame(b, b2); - } - - @Test - public void testGetSetExchangeRateChain() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit baseTerm = TestCurrency.of("EUR"); - CurrencyUnit term = TestCurrency.of("USD"); - DefaultExchangeRate rate1 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(base) - .setTermCurrency(baseTerm).setFactor(TestNumberValue.of(0.8)).build(); - ExchangeRate rate2 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(baseTerm) - .setTermCurrency(term).setFactor(TestNumberValue.of(1.4)).build(); - DefaultExchangeRate.Builder b = - new DefaultExchangeRate.Builder("test", RateType.DEFERRED).setBaseCurrency(base).setTermCurrency(term) - .setRateChain(rate1, rate2); - ExchangeRate rate = - b.setFactor(TestNumberValue.of(9)).setContext(ConversionContext.of("test", RateType.DEFERRED)).build(); - assertEquals(rate.getFactor().numberValue(BigDecimal.class), BigDecimal.valueOf(9)); - assertEquals(rate.getExchangeRateChain(), Arrays.asList(rate1, rate2)); - } - - @Test - public void testGetSetBaseLeadingFactor() { - DefaultExchangeRate.Builder b = new DefaultExchangeRate.Builder("test", RateType.DEFERRED); - DefaultExchangeRate.Builder b2 = b.setFactor(TestNumberValue.of(Long.MAX_VALUE)); - assertSame(b, b2); - b.setFactor(TestNumberValue.of(100L)); - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit term = TestCurrency.of("USD"); - ExchangeRate rate = b.setBaseCurrency(base).setContext(ConversionContext.of("test", RateType.DEFERRED)) - .setTermCurrency(term).build(); - assertEquals(BigDecimal.valueOf(100L), rate.getFactor().numberValue(BigDecimal.class)); - } - - @Test - public void testGetSetTermLeadingFactorBigDecimal() { - DefaultExchangeRate.Builder b = new DefaultExchangeRate.Builder("test", RateType.DEFERRED); - DefaultExchangeRate.Builder b2 = b.setFactor(TestNumberValue.of(1.2)); - assertSame(b, b2); - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit term = TestCurrency.of("USD"); - ExchangeRate rate = b.setBaseCurrency(base).setContext(ConversionContext.of("test", RateType.DEFERRED)) - .setTermCurrency(term).build(); - assertEquals(TestNumberValue.of(1.2), rate.getFactor()); - } - - - @Test - public void testBuild() { - CurrencyUnit base = TestCurrency.of("CHF"); - CurrencyUnit baseTerm = TestCurrency.of("EUR"); - CurrencyUnit term = TestCurrency.of("USD"); - DefaultExchangeRate rate1 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED) - .setContext(ConversionContext.of("test", RateType.DEFERRED)).setBaseCurrency(base) - .setTermCurrency(baseTerm).setFactor(TestNumberValue.of(0.8)).build(); - DefaultExchangeRate rate2 = new DefaultExchangeRate.Builder("test", RateType.DEFERRED) - .setContext(ConversionContext.of("test", RateType.DEFERRED)).setBaseCurrency(baseTerm) - .setTermCurrency(term).setFactor(TestNumberValue.of(1.4)).build(); - - DefaultExchangeRate.Builder b = new DefaultExchangeRate.Builder("test", RateType.DEFERRED); - b.setContext(ConversionContext.of("bla", RateType.DEFERRED)); - b.setBaseCurrency(base); - b.setTermCurrency(term); - b.setFactor(TestNumberValue.of(2.2)); - ExchangeRate rate = b.build(); - assertEquals(rate.getContext(), ConversionContext.of("bla", RateType.DEFERRED)); - assertEquals(base, rate.getBaseCurrency()); - assertEquals(term, rate.getCurrency()); - assertEquals(BigDecimal.valueOf(2.2d), rate.getFactor().numberValue(BigDecimal.class)); - - b = new DefaultExchangeRate.Builder("test", RateType.DEFERRED); - b.setBaseCurrency(TestCurrency.of("CHF")); - b.setTermCurrency(TestCurrency.of("USD")); - b.setRateChain(rate1, rate2); - b.setFactor(TestNumberValue.of(2.0)); - rate = b.build(); - assertEquals(rate.getContext(), ConversionContext.of("test", RateType.DEFERRED)); - assertEquals(TestCurrency.of("CHF"), rate.getBaseCurrency()); - assertEquals(TestCurrency.of("USD"), rate.getCurrency()); - assertEquals(BigDecimal.valueOf(2.0), rate.getFactor().numberValue(BigDecimal.class)); - } -} diff --git a/src/test/java/javax/money/convert/MonetaryConversionsDynamicServiceProviderTest.java b/src/test/java/javax/money/convert/MonetaryConversionsDynamicServiceProviderTest.java deleted file mode 100644 index 0f53cb744..000000000 --- a/src/test/java/javax/money/convert/MonetaryConversionsDynamicServiceProviderTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.testng.Assert.assertEquals; - -import java.util.Arrays; -import java.util.HashSet; - -import javax.money.spi.Bootstrap; -import javax.money.spi.MonetaryConversionsSingletonSpi; -import javax.money.spi.ServiceProvider; - -import org.testng.annotations.Test; - -import javax.money.AbstractDynamicServiceProviderTest; - -/** - * Test to ensure that singleton SPIs used by {@link MonetaryConversions} handle substitution of {@link ServiceProvider} to use when - * calling {@link Bootstrap#init(javax.money.spi.ServiceProvider)}. (e.g. in an OSGI environment) - * @author Matthias Hanisch - * - */ -public class MonetaryConversionsDynamicServiceProviderTest - extends AbstractDynamicServiceProviderTest { - - /** - * Default test SPI: {@link TestMonetaryConversionsSingletonSpi} supports one conversion provider name. - * Dynamic SPI: Mock supporting two conversion provider names. - * Testing following steps: - *

    - *
  • use default SPI
  • - *
  • number of conversion provider names should be one
  • - *
  • use dynamic SPI
  • - *
  • number of conversion provider names should be two
  • - *
  • use default SPI
  • - *
  • number of conversion provider names should be one
  • - *
- */ - @Test - public void testMonetaryConversionsSingletonSpi() { - assertEquals(MonetaryConversions.getConversionProviderNames().size(),1); - MonetaryConversionsSingletonSpi mock = mock(MonetaryConversionsSingletonSpi.class); - doReturn(new HashSet<>(Arrays.asList("conversionProviderOne", "conversionProviderTwo"))).when(mock).getProviderNames(); - registerService(MonetaryConversionsSingletonSpi.class, mock); - initTestServiceProvider(); - assertEquals(MonetaryConversions.getConversionProviderNames().size(),2); - initOriginalServiceProvider(); - assertEquals(MonetaryConversions.getConversionProviderNames().size(),1); - - } -} diff --git a/src/test/java/javax/money/convert/MonetaryConversionsTest.java b/src/test/java/javax/money/convert/MonetaryConversionsTest.java deleted file mode 100644 index 792ad2028..000000000 --- a/src/test/java/javax/money/convert/MonetaryConversionsTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - - -import org.testng.annotations.Test; - -import javax.money.MonetaryException; -import javax.money.TestCurrency; - -import static org.testng.Assert.*; - -/** - * Tests for {@link javax.money.convert.MonetaryConversions}. - */ -public class MonetaryConversionsTest { - @Test - public void testGetConversion() throws Exception { - assertNotNull(MonetaryConversions.getConversion(TestCurrency.of("CHF"))); - } - - @Test - public void testGetConversion1() throws Exception { - assertNotNull(MonetaryConversions.getConversion( - ConversionQueryBuilder.of().setTermCurrency(TestCurrency.of("CHF")).build())); - } - - @Test - public void testGetExchangeRateProvider1() throws Exception { - assertNotNull(MonetaryConversions.getExchangeRateProvider( - ConversionQueryBuilder.of().setTermCurrency(TestCurrency.of("CHF")).build())); - } - - @Test - public void testIsConversionAvailable1_Query() throws Exception { - assertTrue(MonetaryConversions.isConversionAvailable( - ConversionQueryBuilder.of().setTermCurrency(TestCurrency.of("CHF")).build())); - } - - @Test - public void testIsExchangeRateProviderAvailable1_Query() throws Exception { - assertTrue(MonetaryConversions.isExchangeRateProviderAvailable( - ConversionQueryBuilder.of().setTermCurrency(TestCurrency.of("CHF")).build())); - } - - @Test - public void testGetConversion2() throws Exception { - assertNotNull(MonetaryConversions.getConversion( - ConversionQueryBuilder.of().setTermCurrency(TestCurrency.of("CHF")).setProviderNames("test").build())); - try { - MonetaryConversions.getConversion( - ConversionQueryBuilder.of().setTermCurrency(TestCurrency.of("CHF")).setProviderNames("foo").build()); - fail("Should throw MonetaryException"); - } catch (MonetaryException e) { - // OK - } - } - - @Test - public void testIsConversionAvailable2() throws Exception { - assertTrue(MonetaryConversions.isConversionAvailable( - ConversionQueryBuilder.of().setTermCurrency(TestCurrency.of("CHF")).setProviderNames("test").build())); - } - - @Test - public void testGetConversion_String_StringArr() throws Exception { - assertNotNull(MonetaryConversions.getConversion("test1", "test")); - assertNotNull(MonetaryConversions.getConversion("test1")); - try { - MonetaryConversions.getConversion("test1", "foo"); - fail("Should throw MonetaryException"); - } catch (MonetaryException e) { - // OK - } - } - - @Test - public void testIsConversionAvailable_String_StringArr() throws Exception { - assertTrue(MonetaryConversions.isConversionAvailable("test1", "test")); - assertTrue(MonetaryConversions.isConversionAvailable("test1")); - assertFalse(MonetaryConversions.isConversionAvailable("test1", "foo")); - } - - @Test - public void testGetConversion3() throws Exception { - assertNotNull(MonetaryConversions.getConversion(TestCurrency.of("CHF"), "test")); - } - - @Test - public void testGetExchangeRateProvider() throws Exception { - assertNotNull(MonetaryConversions.getExchangeRateProvider("test")); - } - - @Test(expectedExceptions = MonetaryException.class) - public void testGetExchangeRateProvider_Invalid() throws Exception { - MonetaryConversions.getExchangeRateProvider("fooBarAnyBla"); - } - - @Test - public void testGetProviderNames() throws Exception { - assertNotNull(MonetaryConversions.getConversionProviderNames()); - assertTrue(MonetaryConversions.getConversionProviderNames().contains("test")); - assertTrue(MonetaryConversions.getConversionProviderNames().size() == 1); - } - - @Test - public void testGetDefaultProviderChain() throws Exception { - assertNotNull(MonetaryConversions.getDefaultConversionProviderChain()); - assertFalse(MonetaryConversions.getDefaultConversionProviderChain().isEmpty()); - assertEquals(1, MonetaryConversions.getDefaultConversionProviderChain().size()); - } -} diff --git a/src/test/java/javax/money/convert/ProviderContextTest.java b/src/test/java/javax/money/convert/ProviderContextTest.java deleted file mode 100644 index e6cc69e9e..000000000 --- a/src/test/java/javax/money/convert/ProviderContextTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - - -import static org.testng.Assert.*; - -import org.testng.annotations.Test; - -import java.util.HashSet; -import java.util.Set; - -/** - * Tests for {@link javax.money.convert.ProviderContext}. - */ -public class ProviderContextTest { - - @Test - public void testGetRateTypes() throws Exception { - ProviderContext ctx = ProviderContextBuilder.of("myprov", RateType.DEFERRED, RateType.HISTORIC).build(); - assertEquals("myprov", ctx.getProviderName()); - } - - @Test - public void testToBuilder() throws Exception { - ProviderContext ctx = ProviderContextBuilder.of("myprov", RateType.ANY).build(); - assertEquals(ctx, ctx.toBuilder().build()); - } - - @Test - public void testOf() throws Exception { - ProviderContext ctx = ProviderContext.of("testprov"); - ProviderContext ctx2 = ProviderContext.of("testprov"); - assertEquals(ctx, ctx2); - assertEquals("testprov", ctx.getProviderName()); - } - - @Test - public void testOfWithRateType() throws Exception { - ProviderContext ctx = ProviderContext.of("test", RateType.REALTIME); - ProviderContext ctx2 = ProviderContext.of("test", RateType.REALTIME); - assertEquals(ctx, ctx2); - assertNotNull(ctx.getRateTypes()); - assertTrue(ctx.getRateTypes().size() == 1); - assertTrue(ctx.getRateTypes().contains(RateType.REALTIME)); - } - - @Test - public void testProviderContextBuilder() { - Set types = new HashSet<>(); - types.add(RateType.DEFERRED); - types.add(RateType.HISTORIC); - ProviderContextBuilder b = ProviderContextBuilder.of("prov", types); - ProviderContext ctx = b.build(); - assertEquals(ctx.getRateTypes(), types); - } - -} diff --git a/src/test/java/javax/money/convert/TestMonetaryConversionsSingletonSpi.java b/src/test/java/javax/money/convert/TestMonetaryConversionsSingletonSpi.java deleted file mode 100644 index 44b142063..000000000 --- a/src/test/java/javax/money/convert/TestMonetaryConversionsSingletonSpi.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import javax.money.CurrencyUnit; -import javax.money.MonetaryAmount; -import javax.money.MonetaryException; -import javax.money.spi.MonetaryConversionsSingletonSpi; - -/** - * @author Anatole Tresch - * @author Werner - * @version 0.3 on 11.05.14. - */ -public class TestMonetaryConversionsSingletonSpi implements MonetaryConversionsSingletonSpi { - - private final ExchangeRateProvider provider = new DummyRateProvider(); - - - @Override - public ExchangeRateProvider getExchangeRateProvider(ConversionQuery conversionQuery) { - - if (conversionQuery.getProviderNames().isEmpty() || conversionQuery.getProviderNames().contains("test")) { - return provider; - } - throw new MonetaryException("No such rate provider(s): " + conversionQuery.getProviderNames()); - } - - @Override - public boolean isExchangeRateProviderAvailable(ConversionQuery conversionQuery) { - return conversionQuery.getProviderNames().isEmpty() || conversionQuery.getProviderNames().contains("test"); - } - - @Override - public boolean isConversionAvailable(ConversionQuery conversionQuery) { - return conversionQuery.getProviderNames().isEmpty() || conversionQuery.getProviderNames().contains("test"); - } - - @Override - public Collection getProviderNames() { - return Collections.singletonList("test"); - } - - @Override - public List getDefaultProviderChain() { - return new ArrayList<>(getProviderNames()); - } - - private static final class DummyConversion implements CurrencyConversion { - - private final CurrencyUnit termCurrency; - private final ConversionContext ctx = ConversionContext.of(); - - DummyConversion(CurrencyUnit termCurrency) { - this.termCurrency = termCurrency; - } - - @Override - public CurrencyUnit getCurrency() { - return termCurrency; - } - - @Override - public ConversionContext getContext() { - return ctx; - } - - @Override - public ExchangeRate getExchangeRate(MonetaryAmount sourceAmount) { - return new DefaultExchangeRate.Builder(getClass().getSimpleName(), RateType.OTHER) - .setBaseCurrency(sourceAmount.getCurrency()).setTermCurrency(termCurrency) - .setFactor(TestNumberValue.of(1)).build(); - } - - @Override - public ExchangeRateProvider getExchangeRateProvider() { - return null; - } - - @Override - public MonetaryAmount apply(MonetaryAmount value) { - return value; - } - } - - private static final class DummyRateProvider implements ExchangeRateProvider { - - private final ProviderContext ctx = ProviderContext.of("test"); - - @Override - public ProviderContext getContext() { - return ctx; - } - - @Override - public boolean isAvailable(CurrencyUnit base, CurrencyUnit term) { - return false; - } - - @Override - public boolean isAvailable(ConversionQuery conversionContext) { - return false; - } - - @Override - public ExchangeRate getExchangeRate(ConversionQuery query) { - if ("test1".equals(query.getBaseCurrency().getCurrencyCode()) - && "test2".equals(query.getCurrency().getCurrencyCode())) { - return new DefaultExchangeRate.Builder(getClass().getSimpleName(), RateType.OTHER) - .setBaseCurrency(query.getBaseCurrency()).setTermCurrency(query.getCurrency()) - .setFactor(TestNumberValue.of(new BigDecimal("0.5"))).build(); - } - if ("test2".equals(query.getBaseCurrency().getCurrencyCode()) - && "test1".equals(query.getCurrency().getCurrencyCode())) { - return new DefaultExchangeRate.Builder(getClass().getSimpleName(), RateType.OTHER) - .setBaseCurrency(query.getBaseCurrency()).setTermCurrency(query.getCurrency()) - .setFactor(TestNumberValue.of(new BigDecimal("2"))).build(); - } - - return new DefaultExchangeRate.Builder(getClass().getSimpleName(), RateType.OTHER) - .setBaseCurrency(query.getBaseCurrency()).setTermCurrency(query.getCurrency()) - .setFactor(TestNumberValue.of(1)).build(); - } - - @Override - public ExchangeRate getReversed(ExchangeRate rate) { - return getExchangeRate(rate.getCurrency(), rate.getBaseCurrency()); - } - - @Override - public CurrencyConversion getCurrencyConversion(ConversionQuery query) { - return new DummyConversion(query.getCurrency()); - } - - } -} diff --git a/src/test/java/javax/money/convert/TestNumberValue.java b/src/test/java/javax/money/convert/TestNumberValue.java deleted file mode 100644 index 2a9f52827..000000000 --- a/src/test/java/javax/money/convert/TestNumberValue.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.convert; - -import javax.money.NumberValue; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.MathContext; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Default implementation of {@link javax.money.NumberValue} based on {@link java.math.BigDecimal}. - * - * @author Anatole Tresch - * @author Werner Keil - */ -public class TestNumberValue extends NumberValue { - - /** - * serialVersionUID. - */ - private static final long serialVersionUID = 1L; - /** The numeric value. */ - private final Number number; - - - public TestNumberValue(Number number) { - Objects.requireNonNull(number, "Number required"); - this.number = number; - } - - /** - * Creates a new instance of {@link javax.money.NumberValue}, using the given number. - * - * @param number - * The numeric part, not null. - * @return A new instance of {@link javax.money.NumberValue}. - */ - public static NumberValue of(Number number) { - return new TestNumberValue(number); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberValue#getNumberType() - */ - @Override - public Class getNumberType() { - return this.number.getClass(); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberValue#getPrecision() - */ - @Override - public int getPrecision() { - return numberValue(BigDecimal.class).precision(); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberValue#getScale() - */ - @Override - public int getScale() { - return numberValue(BigDecimal.class).scale(); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberBinding#getIntValue() - */ - @Override - public int intValue() { - return this.number.intValue(); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberBinding#getIntValueExact() - */ - @Override - public int intValueExact() { - return getBigDecimal(number).intValueExact(); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberBinding#getLongValue() - */ - @Override - public long longValue() { - return this.number.longValue(); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberBinding#getLongValueExact() - */ - @Override - public long longValueExact() { - return getBigDecimal(number).longValueExact(); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberBinding#getFloatValue() - */ - @Override - public float floatValue() { - return this.number.floatValue(); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberBinding#getDoubleValue() - */ - @Override - public double doubleValue() { - return this.number.doubleValue(); - } - - @Override - public long getAmountFractionNumerator(){ - return 0; - } - - @Override - public long getAmountFractionDenominator(){ - return 0; - } - - /* - * (non-Javadoc) - * @see javax.money.NumberBinding#getDoubleValueExact() - */ - @Override - public double doubleValueExact() { - double d = this.number.doubleValue(); - if (d == Double.NEGATIVE_INFINITY || d == Double.POSITIVE_INFINITY) { - throw new ArithmeticException("Unable to convert to double: " - + this.number); - } - return d; - } - - /* - * (non-Javadoc) - * @see javax.money.NumberBinding#getNumberValue(java.lang.Class) - */ - @SuppressWarnings("unchecked") - @Override - public T numberValue(Class numberType) { - if (BigDecimal.class == numberType) { - return (T) getBigDecimal(number); - } - else if (BigInteger.class == numberType) { - return (T) getBigDecimal(number).toBigInteger(); - } - else if (Double.class == numberType) { - return (T) Double.valueOf(this.number.doubleValue()); - } - else if (Float.class == numberType) { - return (T) Float.valueOf(this.number.floatValue()); - } - else if (Long.class == numberType) { - return (T) Long.valueOf(this.number.longValue()); - } - else if (Integer.class == numberType) { - return (T) Integer.valueOf(this.number.intValue()); - } - else if (Short.class == numberType) { - return (T) Short.valueOf(this.number.shortValue()); - } - else if (Byte.class == numberType) { - return (T) Byte.valueOf(this.number.byteValue()); - } - throw new IllegalArgumentException("Unsupported numeric type: " - + numberType); - } - - @Override - public NumberValue round(MathContext mathContext) { - return new TestNumberValue(new BigDecimal(this.number.toString()).round(mathContext)); - } - - /* - * (non-Javadoc) - * @see javax.money.NumberValue#numberValueExact(java.lang.Class) - */ - @SuppressWarnings("unchecked") - @Override - public T numberValueExact(Class numberType) { - if (BigDecimal.class == numberType) { - return (T) getBigDecimal(number); - } - else if (BigInteger.class == numberType) { - return (T) getBigDecimal(number).toBigIntegerExact(); - } - else if (Double.class == numberType) { - double d = this.number.doubleValue(); - if (d == Double.NEGATIVE_INFINITY || d == Double.POSITIVE_INFINITY) { - throw new ArithmeticException( - "Value not exact mappable to double: " + this.number); - } - return (T) Double.valueOf(d); - } - else if (Float.class == numberType) { - float f = this.number.floatValue(); - if (f == Float.NEGATIVE_INFINITY || f == Float.POSITIVE_INFINITY) { - throw new ArithmeticException( - "Value not exact mappable to float: " + this.number); - } - return (T) Float.valueOf(f); - } - else if (Long.class == numberType) { - return (T) Long.valueOf(getBigDecimal(number).longValueExact()); - } - else if (Integer.class == numberType) { - return (T) Integer.valueOf(getBigDecimal(number).intValueExact()); - } - else if (Short.class == numberType) { - return (T) Short.valueOf(getBigDecimal(number).shortValueExact()); - } - else if (Byte.class == numberType) { - return (T) Short.valueOf(getBigDecimal(number).byteValueExact()); - } - throw new IllegalArgumentException("Unsupported numeric type: " - + numberType); - } - - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof TestNumberValue) { - TestNumberValue other = (TestNumberValue) obj; - return Objects.equals(number, other.number); - } - return false; - } - - @Override - public int hashCode(){ - return Objects.hashCode(number); - } - - /* - * (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return String.valueOf(number); - } - - /** - * Creates a {@link java.math.BigDecimal} from the given {@link Number} doing the valid conversion - * depending the type given. - * - * @param num - * the number type - * @return the corresponding {@link java.math.BigDecimal} - */ - private static BigDecimal getBigDecimal(Number num) { - // try fast equality check first (delegates to identity!) - if (BigDecimal.class.equals(num.getClass())) { - return (BigDecimal) num; - } - if (Long.class.equals(num.getClass()) - || Integer.class.equals(num.getClass()) - || Short.class.equals(num.getClass()) - || Byte.class.equals(num.getClass()) - || AtomicLong.class.equals(num.getClass())) { - return BigDecimal.valueOf(num.longValue()); - } - if (Float.class.equals(num.getClass()) - || Double.class.equals(num.getClass())) { - return new BigDecimal(num.toString()); - } - // try instance of (slower) - if (num instanceof BigDecimal) { - return (BigDecimal) num; - } - if (num instanceof BigInteger) { - return new BigDecimal((BigInteger) num); - } - try { - // Avoid imprecise conversion to double value if at all possible - return new BigDecimal(num.toString()); - } catch (NumberFormatException e) { - // ignore - } - return BigDecimal.valueOf(num.doubleValue()); - } - -} diff --git a/src/test/java/javax/money/format/AmountFormatContextTest.java b/src/test/java/javax/money/format/AmountFormatContextTest.java deleted file mode 100644 index fac11975e..000000000 --- a/src/test/java/javax/money/format/AmountFormatContextTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import org.testng.annotations.Test; - -import javax.money.DummyAmountBuilder; -import javax.money.MonetaryAmountFactory; - -import java.util.Locale; - -import static org.testng.Assert.*; - -public class AmountFormatContextTest { - - - @Test - public void testGetFormatName() throws Exception { - AmountFormatContext ctx = AmountFormatContextBuilder.of("testest").build(); - assertEquals(ctx.getFormatName(), "testest"); - } - - @Test - public void testGetLocale() throws Exception { - AmountFormatContext ctx = AmountFormatContextBuilder.of(Locale.CANADA).build(); - assertEquals(ctx.getLocale(), Locale.CANADA); - } - - @Test - public void testGetParseFactory() throws Exception { - @SuppressWarnings("rawtypes") - MonetaryAmountFactory f = new DummyAmountBuilder(); - AmountFormatContext ctx = AmountFormatContextBuilder.of("blbl2"). - setMonetaryAmountFactory(f).build(); - assertEquals(ctx.getParseFactory(), f); - } - - @Test - public void testToBuilder() throws Exception { - AmountFormatContext ctx = AmountFormatContextBuilder.of(Locale.CANADA).build(); - AmountFormatContextBuilder b = ctx.toBuilder(); - assertNotNull(b); - assertEquals(b.build(), ctx); - } -} \ No newline at end of file diff --git a/src/test/java/javax/money/format/AmountFormatQueryTest.java b/src/test/java/javax/money/format/AmountFormatQueryTest.java deleted file mode 100644 index c181709bb..000000000 --- a/src/test/java/javax/money/format/AmountFormatQueryTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import org.testng.annotations.Test; - -import javax.money.MonetaryOperator; -import java.text.DecimalFormat; -import java.util.*; - -import static org.testng.Assert.*; - -/** - * Tests for {@link AmountFormatQuery}. - */ -public class AmountFormatQueryTest { - @Test - public void testOf() throws Exception{ - AmountFormatQuery style = AmountFormatQuery.of(Locale.ENGLISH); - assertNotNull(style); - DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(Locale.ENGLISH); - assertNotNull(df); - } - - @Test - public void testToBuilder() throws Exception{ - AmountFormatQuery style = AmountFormatQueryBuilder.of(Locale.ENGLISH).build(); - AmountFormatQueryBuilder builder = style.toBuilder(); - assertNotNull(builder); - assertEquals(style, builder.build()); - } - - @Test - public void testHashCode(){ - MonetaryOperator op = value -> value.multiply(2.0d); - assertNotNull(op); - List contexts = new ArrayList<>(); - contexts.add(AmountFormatContextBuilder.of(Locale.GERMAN).build()); - contexts.add(AmountFormatContextBuilder.of(Locale.ENGLISH).build()); - Set hashCodes = new HashSet<>(); - contexts.forEach(amountFormatContext -> hashCodes.add(amountFormatContext.hashCode())); - // Check we have 5 distinct hash codes... - assertTrue(hashCodes.size() == 2); - } - - @Test - public void testEquals(){ - MonetaryOperator op = value -> value.multiply(2.0d); - assertNotNull(op); - List contexts = new ArrayList<>(); - contexts.add(AmountFormatContextBuilder.of(Locale.ENGLISH).build()); - contexts.add(AmountFormatContextBuilder.of(Locale.GERMAN).build()); - Set checkContexts = new HashSet<>(contexts); - // Check we have 5 distinct hash codes... - assertTrue(checkContexts.size() == 2); - } - - @Test - public void testToString() throws Exception{ - AmountFormatContext style = - AmountFormatContextBuilder.of(Locale.GERMAN).set("groupSizes", new int[]{1, 2, 3, 4}) - .set("currencyStyle", "NUMERIC_CODE").set("pattern", "###").build(); - String toString = style.toString(); - assertNotNull(toString); - assertTrue(toString.contains("DE")); - assertTrue(toString.contains("java.util.Locale")); - assertTrue(toString.contains("groupSizes")); - assertTrue(toString.contains("###")); - assertTrue(toString.contains("NUMERIC_CODE")); - assertTrue(toString.contains("currencyStyle")); - assertTrue(toString.contains("AmountFormatContext")); - } -} diff --git a/src/test/java/javax/money/format/MonetaryFormatsDynamicServiceProviderTest.java b/src/test/java/javax/money/format/MonetaryFormatsDynamicServiceProviderTest.java deleted file mode 100644 index bfd111ad4..000000000 --- a/src/test/java/javax/money/format/MonetaryFormatsDynamicServiceProviderTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.testng.Assert.assertEquals; - -import java.util.Arrays; -import java.util.HashSet; - -import javax.money.AbstractDynamicServiceProviderTest; -import javax.money.format.MonetaryFormats.DefaultMonetaryFormatsSingletonSpi; -import javax.money.spi.Bootstrap; -import javax.money.spi.MonetaryFormatsSingletonSpi; -import javax.money.spi.ServiceProvider; - -import org.testng.annotations.Test; - -/** - * Test to ensure that singleton SPIs used by {@link MonetaryFormats} handle substitution of {@link ServiceProvider} to use when - * calling {@link Bootstrap#init(javax.money.spi.ServiceProvider)}. (e.g. in an OSGI environment) - * @author Matthias Hanisch - * - */ -public class MonetaryFormatsDynamicServiceProviderTest - extends AbstractDynamicServiceProviderTest { - - - /** - * Default SPI: {@link DefaultMonetaryFormatsSingletonSpi} supports one format provider name. - * Dynamic SPI: Mock supporting two format provider names. - * Testing following steps: - *
    - *
  • use default SPI
  • - *
  • number of format provider names should be one
  • - *
  • use dynamic SPI
  • - *
  • number of format provider names should be two
  • - *
  • use default SPI
  • - *
  • number of format provider names should be one
  • - *
- */ - @Test - public void testMonetaryFormatsSingletonSpi() { - assertEquals(MonetaryFormats.getFormatProviderNames().size(),1); - MonetaryFormatsSingletonSpi mock = mock(MonetaryFormatsSingletonSpi.class); - doReturn(new HashSet<>(Arrays.asList("formatProviderOne", "formatProviderTow"))).when(mock).getProviderNames(); - registerService(MonetaryFormatsSingletonSpi.class, mock); - initTestServiceProvider(); - assertEquals(MonetaryFormats.getFormatProviderNames().size(),2); - initOriginalServiceProvider(); - assertEquals(MonetaryFormats.getFormatProviderNames().size(),1); - } -} diff --git a/src/test/java/javax/money/format/MonetaryFormatsTest.java b/src/test/java/javax/money/format/MonetaryFormatsTest.java deleted file mode 100644 index ae5de32e6..000000000 --- a/src/test/java/javax/money/format/MonetaryFormatsTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import org.testng.annotations.Test; - -import javax.money.MonetaryException; -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.Set; - -import static org.testng.Assert.*; - -/** - * Tests for {@link MonetaryFormats}. - * - * @author Anatole Tresch - */ -public class MonetaryFormatsTest { - - @Test - public void testGetAmountFormatLocale() { - MonetaryAmountFormat fmt = MonetaryFormats.getAmountFormat(Locale.ENGLISH); - assertNotNull(fmt); - assertEquals(fmt.getClass(), TestAmountFormatProvider.TestFormat.class); - } - - @Test(expectedExceptions = MonetaryException.class) - public void testGetAmountFormatLocale_Invalid() { - MonetaryFormats.getAmountFormat(new Locale("foo", "bar")); - } - - @Test - public void testGetAvailableLocales() { - Set locales = MonetaryFormats.getAvailableLocales(); - assertNotNull(locales); - assertTrue(locales.size() == 1); - assertTrue(locales.contains(Locale.ENGLISH)); - } - - @Test - public void testIsAvailable_Locale_Providers() { - assertTrue(MonetaryFormats.isAvailable(Locale.ENGLISH)); - assertTrue(MonetaryFormats.isAvailable(Locale.ENGLISH, "Test")); - assertTrue(MonetaryFormats.isAvailable(Locale.CANADA)); - assertFalse(MonetaryFormats.isAvailable(Locale.ENGLISH, "foo")); - assertFalse(MonetaryFormats.isAvailable(Locale.CANADA, "foo")); - } - - @Test - public void testIsAvailable_Query() { - assertTrue(MonetaryFormats.isAvailable(AmountFormatQueryBuilder.of("Test") - .setProviderName("TestAmountFormatProvider").build())); - assertTrue(MonetaryFormats.isAvailable(AmountFormatQueryBuilder.of("Test") - .build())); - assertFalse(MonetaryFormats.isAvailable(AmountFormatQueryBuilder.of("Test") - .setProviderName("foo").build())); - } - - @Test - public void testGetAmountFormats_Query() { - Collection formats1 = MonetaryFormats.getAmountFormats(AmountFormatQueryBuilder.of("Test") - .setProviderName("TestAmountFormatProvider").build()); - assertNotNull(formats1); - assertEquals(formats1.size(), 1); - Collection formats2 = MonetaryFormats.getAmountFormats(AmountFormatQueryBuilder.of("Test") - .build()); - assertNotNull(formats2); - assertEquals(formats2.size(), 1); - Collection formats3 = MonetaryFormats.getAmountFormats(AmountFormatQueryBuilder.of("Test") - .setProviderName("foo").build()); - assertNotNull(formats3); - assertEquals(formats3.size(), 0); - } - - @Test - public void testGeAmountFormat_Name_Providers() { - MonetaryAmountFormat f = MonetaryFormats.getAmountFormat("Test", "TestAmountFormatProvider"); - assertNotNull(f); - f = MonetaryFormats.getAmountFormat("Test"); - assertNotNull(f); - try { - f = MonetaryFormats.getAmountFormat("Test", "foo"); - assertNotNull(f); - } catch (MonetaryException e) { - // OK - } - } - - @Test - public void testGetProviderNames() { - Collection provs = MonetaryFormats.getFormatProviderNames(); - assertNotNull(provs); - assertTrue(provs.contains("TestAmountFormatProvider")); - } - - @Test - public void testGetDefaultProviderChain() { - List provs = MonetaryFormats.getDefaultFormatProviderChain(); - assertNotNull(provs); - assertTrue(provs.contains("TestAmountFormatProvider")); - } -} diff --git a/src/test/java/javax/money/format/MonetaryParseExceptionTest.java b/src/test/java/javax/money/format/MonetaryParseExceptionTest.java deleted file mode 100644 index c3f4d35f8..000000000 --- a/src/test/java/javax/money/format/MonetaryParseExceptionTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import org.testng.Assert; -import org.testng.annotations.Test; - -/** - * Tests for {@link javax.money.format.MonetaryParseException}. - */ -public class MonetaryParseExceptionTest{ - @Test - public void testGetErrorIndex() throws Exception{ - MonetaryParseException e = new MonetaryParseException("testInput", 5); - Assert.assertEquals(e.getErrorIndex(), 5); - e = new MonetaryParseException("message", "testInput", 5); - Assert.assertEquals(e.getErrorIndex(), 5); - Assert.assertEquals(e.getMessage(),"message"); - } - - @Test - public void testGetInput() throws Exception{ - MonetaryParseException e = new MonetaryParseException("testInput", 5); - Assert.assertEquals(e.getInput(),"testInput"); - e = new MonetaryParseException("message", "testInput", 5); - Assert.assertEquals(e.getInput(),"testInput"); - Assert.assertEquals(e.getMessage(),"message"); - } - - @Test(expectedExceptions=IllegalArgumentException.class) - public void testCreateIllegalInput(){ - //noinspection ThrowableInstanceNeverThrown - new MonetaryParseException("testInput", 500); - } - - @Test(expectedExceptions=IllegalArgumentException.class) - public void testCreateIllegalInputWithMessage(){ - //noinspection ThrowableInstanceNeverThrown - new MonetaryParseException("message", "testInput", 500); - } -} diff --git a/src/test/java/javax/money/format/TestAmountFormatProvider.java b/src/test/java/javax/money/format/TestAmountFormatProvider.java deleted file mode 100644 index a7fcddac8..000000000 --- a/src/test/java/javax/money/format/TestAmountFormatProvider.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.format; - -import java.io.IOException; -import java.util.*; - -import javax.money.MonetaryAmount; -import javax.money.spi.MonetaryAmountFormatProviderSpi; - -public class TestAmountFormatProvider implements - MonetaryAmountFormatProviderSpi { - - private final Set testSet = new HashSet<>(); - - public TestAmountFormatProvider() { - testSet.add(Locale.ENGLISH); - } - - @Override - public Collection getAmountFormats( - AmountFormatQuery formatStyle) { - if (formatStyle.getProviderNames().contains("foo")) { - return Collections.emptyList(); - } - Locale loc = formatStyle.getLocale(); - if (Objects.nonNull(loc) && "BAR".equals(loc.getCountry()) && "foo".equals(loc.getLanguage())) { - return Collections.emptySet(); - } - List result = new ArrayList<>(); - result.add(new TestFormat(formatStyle)); - return result; - } - - @Override - public Set getAvailableLocales() { - return Collections.unmodifiableSet(testSet); - } - - @Override - public Set getAvailableFormatNames() { - return Collections.emptySet(); - } - - public static final class TestFormat implements MonetaryAmountFormat { - - private final AmountFormatContext formatStyle; - - TestFormat(AmountFormatQuery formatStyle) { - Objects.requireNonNull(formatStyle); - this.formatStyle = AmountFormatContextBuilder.create(formatStyle).build(); - } - - @Override - public String queryFrom(MonetaryAmount amount) { - return toString(); - } - - @Override - public AmountFormatContext getContext() { - return formatStyle; - } - - @Override - public String format(MonetaryAmount amount) { - return "TestFormat:" + amount.toString(); - } - - @Override - public void print(Appendable appendable, MonetaryAmount amount) - throws IOException { - appendable.append(format(amount)); - } - - @Override - public MonetaryAmount parse(CharSequence text) - throws MonetaryParseException { - throw new UnsupportedOperationException("TestFormat only."); - } - - } - -} diff --git a/src/test/java/javax/money/internal/DefaultMonetaryAmountsSingletonQuerySpi.java b/src/test/java/javax/money/internal/DefaultMonetaryAmountsSingletonQuerySpi.java deleted file mode 100644 index afe74444f..000000000 --- a/src/test/java/javax/money/internal/DefaultMonetaryAmountsSingletonQuerySpi.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.internal; - -import javax.money.*; -import javax.money.spi.MonetaryAmountsSingletonQuerySpi; -import java.util.*; - -/** - * Test implementation of MonetaryAmountsSingletonQuerySpi. - */ -public class DefaultMonetaryAmountsSingletonQuerySpi implements MonetaryAmountsSingletonQuerySpi { - - private List> factories = new ArrayList<>(); - - public DefaultMonetaryAmountsSingletonQuerySpi() { - factories.add(new DummyAmountBuilder()); - factories = Collections.unmodifiableList(factories); - } - - @Override - public Collection> getAmountFactories(MonetaryAmountFactoryQuery query) { - if (query.getProviderNames().contains("gigigig2")) { - return Collections.emptyList(); - } - return factories; - } - -} diff --git a/src/test/java/javax/money/internal/DefaultMonetaryAmountsSingletonSpi.java b/src/test/java/javax/money/internal/DefaultMonetaryAmountsSingletonSpi.java deleted file mode 100644 index 54167222e..000000000 --- a/src/test/java/javax/money/internal/DefaultMonetaryAmountsSingletonSpi.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.internal; - -import javax.money.DummyAmount; -import javax.money.MonetaryAmount; -import javax.money.MonetaryAmountFactory; -import javax.money.MonetaryException; -import javax.money.spi.Bootstrap; -import javax.money.spi.MonetaryAmountFactoryProviderSpi; -import javax.money.spi.MonetaryAmountsSingletonSpi; - -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Default implementation of MonetaryAmountsSpi for testing only. - */ -public class DefaultMonetaryAmountsSingletonSpi implements MonetaryAmountsSingletonSpi{ - - private final Map, MonetaryAmountFactoryProviderSpi> factories = new ConcurrentHashMap<>(); - - public DefaultMonetaryAmountsSingletonSpi() { - for (MonetaryAmountFactoryProviderSpi f : Bootstrap - .getServices(MonetaryAmountFactoryProviderSpi.class)) { - factories.put(f.getAmountType(), f); - } - } - - @SuppressWarnings("unchecked") - @Override - public MonetaryAmountFactory getAmountFactory( - Class amountType) { - MonetaryAmountFactoryProviderSpi f = MonetaryAmountFactoryProviderSpi.class - .cast(factories.get(amountType)); - if (Objects.nonNull(f)) { - return f.createMonetaryAmountFactory(); - } - throw new MonetaryException( - "No matching MonetaryAmountFactory found, type=" - + amountType.getName()); - } - - @Override - public Set> getAmountTypes() { - return factories.keySet(); - } - - - @Override - public Class getDefaultAmountType() { - return DummyAmount.class; - } - -} diff --git a/src/test/java/javax/money/internal/package-info.java b/src/test/java/javax/money/internal/package-info.java deleted file mode 100644 index d9bf3987c..000000000 --- a/src/test/java/javax/money/internal/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Package containing default implementations for testing only. - */ -package javax.money.internal; - diff --git a/src/test/java/javax/money/spi/BootstrapTest.java b/src/test/java/javax/money/spi/BootstrapTest.java deleted file mode 100644 index fa8285413..000000000 --- a/src/test/java/javax/money/spi/BootstrapTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import java.util.*; - -import org.testng.annotations.Test; - -import static org.testng.Assert.*; - -/** - * Tests for {@link javax.money.spi.Bootstrap}. - */ -@SuppressWarnings("unchecked") -@Test -public class BootstrapTest { - - @Test - public void testInit_InitTwice() throws Exception { - TestServiceProvider testProv = new TestServiceProvider(); - ServiceProvider prov = Bootstrap.init(testProv); - assertTrue(testProv == Bootstrap.init(prov)); - } - - @Test - public void testInit() throws Exception { - Collection services = Collection.class.cast(Bootstrap.getServices(String.class)); - assertNotNull(services); - assertFalse(services.isEmpty()); - assertTrue(services.contains("service1")); - assertTrue(services.contains("service2")); - services = Collection.class.cast(Bootstrap.getServices(Runtime.class)); - assertNotNull(services); - assertTrue(services.isEmpty()); - } - - @Test - public void testGetServiceProvider() throws Exception { - assertNotNull(Bootstrap.getServiceProvider()); - assertEquals(Bootstrap.getServiceProvider().getClass(), TestServiceProvider.class); - } - - @Test - public void testGetServices() throws Exception { - Collection services = Collection.class.cast(Bootstrap.getServices(String.class)); - assertNotNull(services); - assertFalse(services.isEmpty()); - assertTrue(services.contains("service1")); - assertTrue(services.contains("service2")); - services = Collection.class.cast(Bootstrap.getServices(Runtime.class)); - assertNotNull(services); - assertTrue(services.isEmpty()); - } - - @Test - public void testGetService() throws Exception { - Integer num = Bootstrap.getService(Integer.class); - assertNotNull(num); - assertTrue(num.equals(5)); - } - - @Test - public void testGetService_BadCase() throws Exception { - assertNull(Bootstrap.getService(Locale.class)); - } - - public final static class TestServiceProvider extends DefaultServiceProvider - implements ServiceProvider { - - @Override - public List getServices(Class serviceType) { - if (String.class.equals(serviceType)) { - return List.class.cast(Arrays.asList("service1", "service2")); - } else if (Integer.class.equals(serviceType)) { - return List.class.cast(Collections.singletonList(5)); - } else if (Long.class.equals(serviceType)) { - return List.class.cast(Collections.singletonList((long) 111)); - } - return super.getServices(serviceType); - } - - } -} diff --git a/src/test/java/javax/money/spi/ConcurrentInitializationTest.java b/src/test/java/javax/money/spi/ConcurrentInitializationTest.java deleted file mode 100644 index dbe5fffa3..000000000 --- a/src/test/java/javax/money/spi/ConcurrentInitializationTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import org.testng.annotations.Test; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.money.DummyAmount; -import javax.money.DummyAmountBuilder; -import javax.money.Monetary; -import javax.money.MonetaryAmount; - -import static org.testng.AssertJUnit.assertEquals; - -/** - * Test concurrent initialization/bootstrapping of {@link javax.money.spi.Bootstrap}. - */ -public class ConcurrentInitializationTest { - - static class Round implements Runnable { - private final MonetaryAmount amount; - - Round(final MonetaryAmount amount) { - this.amount = amount; - } - - @Override - public void run() { - Monetary.getDefaultRounding().apply(amount); - } - } - - private static final int THREAD_COUNT = 100; - - /** - * https://github.com/JavaMoney/jsr354-ri/issues/30. - */ - @Test - public void shouldSupportConcurrentInitialization() throws InterruptedException { - final DummyAmount amount = new DummyAmountBuilder().create(); - - final List threads = new ArrayList<>(THREAD_COUNT); - final List throwables = Collections.synchronizedList(new ArrayList<>()); - final Thread.UncaughtExceptionHandler uncaughtExceptionHandler = (t, e) -> throwables.add(e); - - for (int i = 0; i < THREAD_COUNT; i++) { - final Thread thread = new Thread(new Round(amount)); - thread.setUncaughtExceptionHandler(uncaughtExceptionHandler); - thread.start(); - threads.add(thread); - } - - for (Thread thread : threads) { - thread.join(); - } - - throwables.forEach(java.lang.Throwable::printStackTrace); - assertEquals(0, throwables.size()); - - } -} diff --git a/src/test/java/javax/money/spi/CurrencyProviderSpiTest.java b/src/test/java/javax/money/spi/CurrencyProviderSpiTest.java deleted file mode 100644 index 1db194d29..000000000 --- a/src/test/java/javax/money/spi/CurrencyProviderSpiTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import org.testng.annotations.Test; - -import javax.money.CurrencyQueryBuilder; -import javax.money.CurrencyUnit; -import javax.money.TestCurrency; -import java.util.HashSet; -import java.util.Set; - -import static org.testng.Assert.*; - -/** - * Test class to test the default methods of CurrencyProviderSpi. - */ -public class CurrencyProviderSpiTest { - - private static final CurrencyProviderSpi testProvider = query -> { - Set result = new HashSet<>(); - if (query.getCurrencyCodes().contains("CHF")) { - result.add(TestCurrency.of("CHF")); - } - return result; - }; - - @Test - public void testGetProviderName() throws Exception { - assertEquals(testProvider.getProviderName(), testProvider.getClass().getSimpleName()); - - } - - @Test - public void testIsCurrencyAvailable() throws Exception { - assertTrue(testProvider.isCurrencyAvailable(CurrencyQueryBuilder.of().setCurrencyCodes("CHF").build())); - assertFalse(testProvider.isCurrencyAvailable(CurrencyQueryBuilder.of().setCurrencyCodes("foofoo").build())); - } - -} \ No newline at end of file diff --git a/src/test/java/javax/money/spi/MonetaryAmountFactoryProviderSpiTest.java b/src/test/java/javax/money/spi/MonetaryAmountFactoryProviderSpiTest.java deleted file mode 100644 index a15158f4a..000000000 --- a/src/test/java/javax/money/spi/MonetaryAmountFactoryProviderSpiTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import static javax.money.spi.MonetaryAmountFactoryProviderSpi.QueryInclusionPolicy; -import static javax.money.spi.MonetaryAmountFactoryProviderSpi.QueryInclusionPolicy.ALWAYS; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.CoreMatchers.sameInstance; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import javax.money.MonetaryAmountFactory; -import javax.money.MonetaryContext; -import javax.money.MonetaryContextBuilder; - -/** - * unit test. - */ -public class MonetaryAmountFactoryProviderSpiTest { - - private MonetaryAmountFactoryProviderSpiTestStub sut; - private MonetaryContext monetaryContext; - - @BeforeMethod - public void setUp(){ - monetaryContext = MonetaryContextBuilder.of().build(); - sut = new MonetaryAmountFactoryProviderSpiTestStub(monetaryContext); - } - - @Test - public void shouldReturnQueryInclusionPolicyALWAYS() { - // when - QueryInclusionPolicy result = sut.getQueryInclusionPolicy(); - // then - assertThat(result, is(ALWAYS)); - } - - @Test - public void getMaximalMonetaryContextShouldReturnDefault(){ - // given - // when - MonetaryContext result = sut.getMaximalMonetaryContext(); - // then - assertThat(result, sameInstance(monetaryContext)); - } - - @SuppressWarnings("rawtypes") - private static final class MonetaryAmountFactoryProviderSpiTestStub implements MonetaryAmountFactoryProviderSpi { - - private final MonetaryContext monetaryContext; - - MonetaryAmountFactoryProviderSpiTestStub(MonetaryContext monetaryContext) { - this.monetaryContext = monetaryContext; - } - - @Override - public Class getAmountType() { - return null; - } - - @Override - public MonetaryAmountFactory createMonetaryAmountFactory() { - return null; - } - - @Override - public MonetaryContext getDefaultMonetaryContext() { - return monetaryContext; - } - } -} diff --git a/src/test/java/javax/money/spi/MonetaryAmountsSingletonQuerySpiTest.java b/src/test/java/javax/money/spi/MonetaryAmountsSingletonQuerySpiTest.java deleted file mode 100644 index b80fdadad..000000000 --- a/src/test/java/javax/money/spi/MonetaryAmountsSingletonQuerySpiTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import javax.money.*; -import java.util.ArrayList; -import java.util.List; - -import static org.testng.AssertJUnit.*; - -/** - * Tests the default methods on MonetaryAmountsSingletonQuerySpi. - */ -public class MonetaryAmountsSingletonQuerySpiTest { - - private final MonetaryAmountsSingletonQuerySpi testSpi = query -> { - List> factories = new ArrayList<>(); - if (query.getBoolean("select")) { - factories.add(new DummyAmountBuilder()); - } - return factories; - }; - - public void testIsAvailable() { - assertTrue(testSpi.isAvailable(MonetaryAmountFactoryQueryBuilder.of().set("select", true).build())); - assertFalse(testSpi.isAvailable(MonetaryAmountFactoryQueryBuilder.of().set("select", false).build())); - } - - public void testGetAmountType() { - assertEquals(DummyAmount.class, testSpi.getAmountType(MonetaryAmountFactoryQueryBuilder.of().set("select", true).build())); - assertEquals(null, testSpi.getAmountType(MonetaryAmountFactoryQueryBuilder.of().set("select", false).build())); - } - - public void testGetAmountTypes() { - assertFalse(testSpi.getAmountTypes(MonetaryAmountFactoryQueryBuilder.of().set("select", true).build()).isEmpty()); - assertTrue(testSpi.getAmountTypes(MonetaryAmountFactoryQueryBuilder.of().set("select", false).build()).isEmpty()); - } - - public void testGetAmountFactory() { - assertNotNull(testSpi.getAmountFactory(MonetaryAmountFactoryQueryBuilder.of().set("select", true).build())); - assertNull(testSpi.getAmountFactory(MonetaryAmountFactoryQueryBuilder.of().set("select", false).build())); - } - -} diff --git a/src/test/java/javax/money/spi/MonetaryAmountsSingletonSpiTest.java b/src/test/java/javax/money/spi/MonetaryAmountsSingletonSpiTest.java deleted file mode 100644 index 2865733a7..000000000 --- a/src/test/java/javax/money/spi/MonetaryAmountsSingletonSpiTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import org.testng.annotations.Test; - -import javax.money.DummyAmount; -import javax.money.DummyAmountBuilder; -import javax.money.MonetaryAmount; -import javax.money.MonetaryAmountFactory; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertFalse; -import static org.testng.AssertJUnit.assertNotNull; - -/** - * Tests the default methods on MonetaryAmountsSingletonSpi. - */ -public class MonetaryAmountsSingletonSpiTest { - - private final MonetaryAmountsSingletonSpi testSpi = new MonetaryAmountsSingletonSpi() { - @SuppressWarnings("unchecked") - @Override - public MonetaryAmountFactory getAmountFactory(Class amountType) { - if (amountType.equals(DummyAmount.class)) { - return (MonetaryAmountFactory) new DummyAmountBuilder(); - } - return null; - } - - @Override - public Class getDefaultAmountType() { - return DummyAmount.class; - } - - @Override - public Collection> getAmountTypes() { - Set> result = new HashSet<>(); - result.add(DummyAmount.class); - return result; - } - }; - - @Test - public void testGetDefaultAmountFactory() { - assertNotNull(testSpi.getDefaultAmountFactory()); - assertEquals(DummyAmountBuilder.class, testSpi.getDefaultAmountFactory().getClass()); - } - - @Test - public void testGetAmountFactories() { - Collection> factories = testSpi.getAmountFactories(); - assertNotNull(factories); - assertFalse(factories.isEmpty()); - assertEquals(1, factories.size()); - assertEquals(DummyAmountBuilder.class, factories.iterator().next().getClass()); - } - -} diff --git a/src/test/java/javax/money/spi/MonetaryConversionsSingletonSpiTest.java b/src/test/java/javax/money/spi/MonetaryConversionsSingletonSpiTest.java deleted file mode 100644 index 45ee7a0ea..000000000 --- a/src/test/java/javax/money/spi/MonetaryConversionsSingletonSpiTest.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import org.testng.annotations.Test; - -import javax.money.*; -import javax.money.convert.*; -import java.util.*; - -import static org.testng.AssertJUnit.*; - -/** - * Tests the default methods on MonetaryAmountsSingletonSpi. - */ -public class MonetaryConversionsSingletonSpiTest { - - private final MonetaryConversionsSingletonSpi testSpi = new MonetaryConversionsSingletonSpi() { - - @Override - public Collection getProviderNames() { - return Arrays.asList("b", "a"); - } - - @Override - public List getDefaultProviderChain() { - return Arrays.asList("a", "b"); - } - - @Override - public ExchangeRateProvider getExchangeRateProvider(ConversionQuery conversionQuery) { - if (conversionQuery.getProviderNames().contains("a")) { - return new ExchangeRateProvider() { - @Override - public ProviderContext getContext() { - return ProviderContext.of("a"); - } - - @Override - public ExchangeRate getExchangeRate(ConversionQuery conversionQuery) { - return null; - } - - @Override - public CurrencyConversion getCurrencyConversion(ConversionQuery conversionQuery) { - return new CurrencyConversion() { - @Override - public ConversionContext getContext() { - return null; - } - - @Override - public ExchangeRate getExchangeRate(MonetaryAmount sourceAmount) { - return null; - } - - @Override - public ExchangeRateProvider getExchangeRateProvider() { - return null; - } - - @Override - public CurrencyUnit getCurrency() { - return null; - } - - @Override - public MonetaryAmount apply(MonetaryAmount monetaryAmount) { - return null; - } - }; - } - }; - } else if (conversionQuery.getProviderNames().contains("b")) { - return new ExchangeRateProvider() { - @Override - public ProviderContext getContext() { - return ProviderContext.of("b"); - } - - @Override - public ExchangeRate getExchangeRate(ConversionQuery conversionQuery) { - return null; - } - - @Override - public CurrencyConversion getCurrencyConversion(ConversionQuery conversionQuery) { - return new CurrencyConversion() { - @Override - public ConversionContext getContext() { - return null; - } - - @Override - public ExchangeRate getExchangeRate(MonetaryAmount sourceAmount) { - return null; - } - - @Override - public ExchangeRateProvider getExchangeRateProvider() { - return null; - } - - @Override - public CurrencyUnit getCurrency() { - return null; - } - - @Override - public MonetaryAmount apply(MonetaryAmount monetaryAmount) { - return null; - } - }; - } - }; - } - return null; - } - }; - - @Test - public void testGetExchangeRateProvider() { - assertNotNull(testSpi.getExchangeRateProvider("a")); - assertNull(testSpi.getExchangeRateProvider("foo")); - } - - @Test - public void testGetExchangeRateProviders() { - assertFalse(testSpi.getExchangeRateProviders("a").isEmpty()); - assertFalse(testSpi.getExchangeRateProviders("b").isEmpty()); - assertFalse(testSpi.getExchangeRateProviders("a", "b").isEmpty()); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetExchangeRateProviders_BC1() { - assertTrue(testSpi.getExchangeRateProviders("foo").isEmpty()); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetExchangeRateProviders_BC2() { - assertTrue(testSpi.getExchangeRateProviders("foo", "a").isEmpty()); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetExchangeRateProviders_BC3() { - assertTrue(testSpi.getExchangeRateProviders("a", "foo").isEmpty()); - } - - @Test - public void testIsConversionAvailable() { - assertTrue(testSpi.isConversionAvailable(ConversionQueryBuilder.of().setProviderNames("a").setTermCurrency(TestCurrency.of("CHF")).build())); - assertTrue(testSpi.isConversionAvailable(ConversionQueryBuilder.of().setProviderNames("b").setTermCurrency(TestCurrency.of("CHF")).build())); - assertTrue(testSpi.isConversionAvailable(ConversionQueryBuilder.of().setProviderNames("b", "b").setTermCurrency(TestCurrency.of("CHF")).build())); - assertFalse(testSpi.isConversionAvailable(ConversionQueryBuilder.of().setProviderNames("foo").setTermCurrency(TestCurrency.of("CHF")).build())); - } - -} diff --git a/src/test/java/javax/money/spi/MonetaryFormatsSingletonSpiTest.java b/src/test/java/javax/money/spi/MonetaryFormatsSingletonSpiTest.java deleted file mode 100644 index 33ada7c8a..000000000 --- a/src/test/java/javax/money/spi/MonetaryFormatsSingletonSpiTest.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import org.testng.annotations.Test; - -import javax.money.*; -import javax.money.format.*; -import java.io.IOException; -import java.util.*; - -import static org.testng.AssertJUnit.*; - -/** - * Tests the default methods on MonetaryAmountsSingletonSpi. - */ -public class MonetaryFormatsSingletonSpiTest { - - private final MonetaryFormatsSingletonSpi testSpi = new MonetaryFormatsSingletonSpi() { - - @Override - public Set getAvailableLocales(String... providers) { - Set locales = new HashSet<>(); - locales.add(Locale.ENGLISH); - return locales; - } - - @Override - public Collection getAmountFormats(AmountFormatQuery formatQuery) { - List formats = new ArrayList<>(); - if (Locale.ENGLISH.equals(formatQuery.getLocale())) { - formats.add(new PseudoFormat()); - } else if ("f1".equals(formatQuery.getFormatName())) { - formats.add(new PseudoFormat()); - } - return formats; - } - - @Override - public Set getProviderNames() { - Set names = new HashSet<>(); - names.add("b"); - return names; - } - - @Override - public List getDefaultProviderChain() { - List names = new ArrayList<>(); - names.add("b"); - return names; - } - - class PseudoFormat implements MonetaryAmountFormat { - - @Override - public AmountFormatContext getContext() { - return AmountFormatContextBuilder.of(Locale.ENGLISH).build(); - } - - @Override - public void print(Appendable appendable, MonetaryAmount amount) throws IOException { - appendable.append(""); - } - - @Override - public MonetaryAmount parse(CharSequence text) throws MonetaryParseException { - return new DummyAmountBuilder().setCurrency(TestCurrency.of("CHF")).setNumber(10.5).create(); - } - - @Override - public String queryFrom(MonetaryAmount amount) { - return ""; - } - } - - }; - - - @Test - public void testGetAmountFormat_Query() { - MonetaryAmountFormat f = testSpi.getAmountFormat(AmountFormatQueryBuilder.of(Locale.ENGLISH).build()); - assertNotNull(f); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetAmountFormat_Query_BC() { - testSpi.getAmountFormat(AmountFormatQueryBuilder.of(Locale.CHINESE).build()); - } - - - @Test - public void testIsAvailable_Query() { - assertTrue(testSpi.isAvailable(AmountFormatQueryBuilder.of(Locale.ENGLISH).build())); - assertFalse(testSpi.isAvailable(AmountFormatQueryBuilder.of(Locale.CHINESE).build())); - } - - @Test - public void testIsAvailable_Locale_StringArr() { - assertTrue(testSpi.isAvailable(Locale.ENGLISH)); - assertFalse(testSpi.isAvailable(Locale.CHINESE)); - assertTrue(testSpi.isAvailable(Locale.ENGLISH, "b")); - assertFalse(testSpi.isAvailable(Locale.CHINESE, "b")); - assertTrue(testSpi.isAvailable(Locale.ENGLISH, "dsdsd")); - assertFalse(testSpi.isAvailable(Locale.CHINESE, "sdsd")); - } - - @Test - public void testGetAmountFormat_Locale_StringArr() { - assertNotNull(testSpi.getAmountFormat(Locale.ENGLISH)); - assertNotNull(testSpi.getAmountFormat(Locale.ENGLISH, "b")); - assertNotNull(testSpi.getAmountFormat(Locale.ENGLISH, "dsdsd")); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetAmountFormat_Locale_StringArr_BC1() { - testSpi.getAmountFormat(Locale.CHINESE); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetAmountFormat_Locale_StringArr_BC2() { - testSpi.getAmountFormat(Locale.CHINESE, "b"); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetAmountFormat_Locale_StringArr_BC3() { - testSpi.getAmountFormat(Locale.CHINESE, "sdsd"); - } - - @Test - public void testGetAmountFormat_String_StringArr() { - assertNotNull(testSpi.getAmountFormat("f1")); - assertNotNull(testSpi.getAmountFormat("f1", "b")); - assertNotNull(testSpi.getAmountFormat("f1", "dsdsd")); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetAmountFormat_String_StringArr_BC1() { - assertNull(testSpi.getAmountFormat("foo")); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetAmountFormat_String_StringArr_BC2() { - assertNull(testSpi.getAmountFormat("foo", "b")); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetAmountFormat_String_StringArr_BC3() { - assertNull(testSpi.getAmountFormat("foo", "sdsd")); - } - -} diff --git a/src/test/java/javax/money/spi/MonetaryRoundingsSingletonSpiTest.java b/src/test/java/javax/money/spi/MonetaryRoundingsSingletonSpiTest.java deleted file mode 100644 index a0a735e54..000000000 --- a/src/test/java/javax/money/spi/MonetaryRoundingsSingletonSpiTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import org.testng.annotations.Test; - -import javax.money.*; -import java.util.*; - -import static org.testng.AssertJUnit.*; - -/** - * Tests the default methods on MonetaryAmountsSingletonSpi. - */ -public class MonetaryRoundingsSingletonSpiTest { - - private static final MonetaryRounding R1 = new MonetaryRounding() { - @Override - public RoundingContext getRoundingContext() { - return null; - } - - @Override - public MonetaryAmount apply(MonetaryAmount monetaryAmount) { - return monetaryAmount; - } - }; - - private final MonetaryRoundingsSingletonSpi testSpi = new MonetaryRoundingsSingletonSpi() { - - @Override - public Set getRoundingNames(String... providers) { - Set roundings = new HashSet<>(); - roundings.add("r1"); - return roundings; - } - - @Override - public Set getProviderNames() { - Set providers = new HashSet<>(); - providers.add("p"); - return providers; - } - - @Override - public List getDefaultProviderChain() { - List providers = new ArrayList<>(); - providers.add("a"); - return providers; - } - - @Override - public Collection getRoundings(RoundingQuery query) { - List roundings = new ArrayList<>(); - if ("r1".equals(query.getRoundingName())) { - roundings.add(R1); - } else if (query.getCurrency() != null && "USD".equals(query.getCurrency().getCurrencyCode())) { - roundings.add(R1); - } - return roundings; - } - - @Override - public MonetaryRounding getDefaultRounding() { - return R1; - } - - }; - - - @Test - public void testGetRounding_CurrencyUnit_StringArr() { - MonetaryRounding r = testSpi.getRounding(TestCurrency.of("USD"), "p"); - assertNotNull(r); - } - - @Test(expectedExceptions = {MonetaryException.class}) - public void testGetRounding_CurrencyUnit_StringArr_BC() { - testSpi.getRounding(TestCurrency.of("EUR"), "p"); - } - - @Test - public void testGetRounding_String_StringArr() { - assertNotNull(testSpi.getRounding("r1")); - assertNotNull(testSpi.getRounding("r1", "p")); - } - - @Test - public void testGetRounding_RoundingQuery() { - assertNotNull(testSpi.getRounding(RoundingQueryBuilder.of().setRoundingName("r1").build())); - } - - @Test - public void tesIsRoundingAvailable() { - assertTrue(testSpi.isRoundingAvailable(RoundingQueryBuilder.of().setRoundingName("r1").build())); - assertFalse(testSpi.isRoundingAvailable(RoundingQueryBuilder.of().setRoundingName("hgfhgf").build())); - } - - @Test - public void tesIsRoundingAvailable_String_StringArr() { - assertTrue(testSpi.isRoundingAvailable("r1")); - assertFalse(testSpi.isRoundingAvailable("sdsd")); - } - - @Test - public void tesIsRoundingAvailable_CurrencyUnit_StringArr() { - assertTrue(testSpi.isRoundingAvailable(TestCurrency.of("USD"), "p")); - assertTrue(testSpi.isRoundingAvailable(TestCurrency.of("USD"))); - assertFalse(testSpi.isRoundingAvailable(TestCurrency.of("CHF"))); - assertFalse(testSpi.isRoundingAvailable(TestCurrency.of("CHF"), "p")); - } - -} diff --git a/src/test/java/javax/money/spi/MonetarySingletonSpiTest.java b/src/test/java/javax/money/spi/MonetarySingletonSpiTest.java deleted file mode 100644 index 418eda08d..000000000 --- a/src/test/java/javax/money/spi/MonetarySingletonSpiTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2012-2016 Credit Suisse - * Copyright 2018-2020 Werner Keil, Otavio Santana, Trivadis AG - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package javax.money.spi; - -import org.testng.annotations.Test; - -import javax.money.CurrencyQuery; -import javax.money.CurrencyQueryBuilder; -import javax.money.CurrencyUnit; -import javax.money.TestCurrency; -import java.util.*; - -import static org.testng.AssertJUnit.*; - -/** - * Tests the default methods on MonetaryAmountsSingletonSpi. - */ -public class MonetarySingletonSpiTest { - - private final MonetaryCurrenciesSingletonSpi testSpi = new MonetaryCurrenciesSingletonSpi() { - - @Override - public List getDefaultProviderChain() { - return Collections.singletonList("a"); - } - - @Override - public Set getProviderNames() { - return new HashSet<>(Arrays.asList("a", "b")); - } - - @Override - public Set getCurrencies(CurrencyQuery query) { - Collection codes = query.getCurrencyCodes(); - if (codes.size() == 1) { - return new HashSet<>(Arrays.asList(TestCurrency.of("USD"))); - } - Collection providers = query.getProviderNames(); - if (providers.size() == 1) { - return new HashSet<>(Arrays.asList(TestCurrency.of("CHF"))); - } - Collection countries = query.getCountries(); - if (!countries.isEmpty()) { - return new HashSet<>(Arrays.asList(TestCurrency.of("EUR"))); - } - return Collections.emptySet(); - } - }; - - @Test - public void testGetCurrency_String() { - CurrencyUnit cu = testSpi.getCurrency("a"); - assertNotNull(cu); - assertEquals(cu.getCurrencyCode(), "USD"); - cu = testSpi.getCurrency("scbjshbd"); - assertNotNull(cu); - assertEquals(cu.getCurrencyCode(), "USD"); - } - - @Test - public void testGetCurrency_Locale() { - // CurrencyUnit getCurrency(Locale country, String... providers) - CurrencyUnit cu = testSpi.getCurrency(Locale.GERMANY, "a"); - assertNotNull(cu); - } - - @Test - public void testGetCurrencies_Locale() { - Set curs = testSpi.getCurrencies(Locale.FRANCE, "a"); - assertNotNull(curs); - } - - @Test - public void testIsCurrencyAvailable_String() { - assertTrue(testSpi.isCurrencyAvailable("CHF", "a")); - assertTrue(testSpi.isCurrencyAvailable("CHF")); - assertTrue(testSpi.isCurrencyAvailable("foo2", "a")); - assertTrue(testSpi.isCurrencyAvailable("foo2")); - } - - @Test - public void testIsCurrencyAvailable_Locale() { - assertTrue(testSpi.isCurrencyAvailable(Locale.GERMANY, "a")); - assertTrue(testSpi.isCurrencyAvailable(Locale.GERMANY)); - assertTrue(testSpi.isCurrencyAvailable(Locale.ROOT, "a")); - assertTrue(testSpi.isCurrencyAvailable(Locale.ROOT)); - } - - @Test - public void testGetCurrencies_String() { - Set curs = testSpi.getCurrencies("a"); - assertNotNull(curs); - assertFalse(curs.isEmpty()); - curs = testSpi.getCurrencies(); - assertNotNull(curs); - assertTrue(curs.isEmpty()); - curs = testSpi.getCurrencies("fooBar"); - assertNotNull(curs); - assertFalse(curs.isEmpty()); - } - - @Test - public void testGetCurrency_Query() { - CurrencyUnit cu = testSpi.getCurrency(CurrencyQueryBuilder.of().setCurrencyCodes("CHF").build()); - assertNotNull(cu); - cu = testSpi.getCurrency(CurrencyQueryBuilder.of().setCurrencyCodes("fooBar").build()); - assertNotNull(cu); - assertEquals(cu.getCurrencyCode(), "USD"); - } - -} diff --git a/src/test/resources/META-INF/services/javax.money.spi.CurrencyProviderSpi b/src/test/resources/META-INF/services/javax.money.spi.CurrencyProviderSpi deleted file mode 100644 index e3206c116..000000000 --- a/src/test/resources/META-INF/services/javax.money.spi.CurrencyProviderSpi +++ /dev/null @@ -1,11 +0,0 @@ -# -# CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE -# CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. -# PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY -# DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE -# AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" -# BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency -# API ("Specification") Copyright (c) 2012-2013, Credit Suisse All rights -# reserved. -# -javax.money.TestCurrencyProvider diff --git a/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountFactoryProviderSpi b/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountFactoryProviderSpi deleted file mode 100644 index aa93e6e12..000000000 --- a/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountFactoryProviderSpi +++ /dev/null @@ -1,11 +0,0 @@ -# -# CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE -# CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. -# PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY -# DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE -# AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" -# BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency -# API ("Specification") Copyright (c) 2012-2013, Credit Suisse All rights -# reserved. -# -javax.money.DummyAmountFactoryProvider diff --git a/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountFormatProviderSpi b/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountFormatProviderSpi deleted file mode 100644 index 1443e7b2f..000000000 --- a/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountFormatProviderSpi +++ /dev/null @@ -1,11 +0,0 @@ -# -# CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE -# CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. -# PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY -# DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE -# AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" -# BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency -# API ("Specification") Copyright (c) 2012-2013, Credit Suisse All rights -# reserved. -# -javax.money.format.TestAmountFormatProvider diff --git a/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountsSingletonQuerySpi b/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountsSingletonQuerySpi deleted file mode 100644 index 664930ad8..000000000 --- a/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountsSingletonQuerySpi +++ /dev/null @@ -1 +0,0 @@ -javax.money.internal.DefaultMonetaryAmountsSingletonQuerySpi diff --git a/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountsSingletonSpi b/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountsSingletonSpi deleted file mode 100644 index fc838d2ae..000000000 --- a/src/test/resources/META-INF/services/javax.money.spi.MonetaryAmountsSingletonSpi +++ /dev/null @@ -1,12 +0,0 @@ -# -# CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE -# CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. -# PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY -# DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE -# AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" -# BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency -# API ("Specification") Copyright (c) 2012-2013, Credit Suisse All rights -# reserved. -# - -javax.money.internal.DefaultMonetaryAmountsSingletonSpi diff --git a/src/test/resources/META-INF/services/javax.money.spi.MonetaryConversionsSingletonSpi b/src/test/resources/META-INF/services/javax.money.spi.MonetaryConversionsSingletonSpi deleted file mode 100644 index ea37c11d7..000000000 --- a/src/test/resources/META-INF/services/javax.money.spi.MonetaryConversionsSingletonSpi +++ /dev/null @@ -1,11 +0,0 @@ -# -# CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE -# CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. -# PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY -# DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE -# AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" -# BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency -# API ("Specification") Copyright (c) 2012-2013, Credit Suisse All rights -# reserved. -# -javax.money.convert.TestMonetaryConversionsSingletonSpi diff --git a/src/test/resources/META-INF/services/javax.money.spi.RoundingProviderSpi b/src/test/resources/META-INF/services/javax.money.spi.RoundingProviderSpi deleted file mode 100644 index 34b0507e6..000000000 --- a/src/test/resources/META-INF/services/javax.money.spi.RoundingProviderSpi +++ /dev/null @@ -1,11 +0,0 @@ -# -# CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE -# CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. -# PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY -# DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE -# AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" -# BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency -# API ("Specification") Copyright (c) 2012-2013, Credit Suisse All rights -# reserved. -# -javax.money.TestRoundingProvider diff --git a/src/test/resources/META-INF/services/javax.money.spi.ServiceProvider b/src/test/resources/META-INF/services/javax.money.spi.ServiceProvider deleted file mode 100644 index 926f38651..000000000 --- a/src/test/resources/META-INF/services/javax.money.spi.ServiceProvider +++ /dev/null @@ -1,11 +0,0 @@ -# -# CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE -# CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. -# PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT CAREFULLY. BY -# DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF THE -# AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" -# BUTTON AT THE BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency -# API ("Specification") Copyright (c) 2012-2013, Credit Suisse All rights -# reserved. -# -javax.money.spi.BootstrapTest$TestServiceProvider \ No newline at end of file diff --git a/stylesheets/print.css b/stylesheets/print.css new file mode 100644 index 000000000..541695bfd --- /dev/null +++ b/stylesheets/print.css @@ -0,0 +1,226 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +body { + font-size: 13px; + line-height: 1.5; + font-family: 'Helvetica Neue', Helvetica, Arial, serif; + color: #000; +} + +a { + color: #d5000d; + font-weight: bold; +} + +header { + padding-top: 35px; + padding-bottom: 10px; +} + +header h1 { + font-weight: bold; + letter-spacing: -1px; + font-size: 48px; + color: #303030; + line-height: 1.2; +} + +header h2 { + letter-spacing: -1px; + font-size: 24px; + color: #aaa; + font-weight: normal; + line-height: 1.3; +} +#downloads { + display: none; +} +#main_content { + padding-top: 20px; +} + +code, pre { + font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; + color: #222; + margin-bottom: 30px; + font-size: 12px; +} + +code { + padding: 0 3px; +} + +pre { + border: solid 1px #ddd; + padding: 20px; + overflow: auto; +} +pre code { + padding: 0; +} + +ul, ol, dl { + margin-bottom: 20px; +} + + +/* COMMON STYLES */ + +table { + width: 100%; + border: 1px solid #ebebeb; +} + +th { + font-weight: 500; +} + +td { + border: 1px solid #ebebeb; + text-align: center; + font-weight: 300; +} + +form { + background: #f2f2f2; + padding: 20px; + +} + + +/* GENERAL ELEMENT TYPE STYLES */ + +h1 { + font-size: 2.8em; +} + +h2 { + font-size: 22px; + font-weight: bold; + color: #303030; + margin-bottom: 8px; +} + +h3 { + color: #d5000d; + font-size: 18px; + font-weight: bold; + margin-bottom: 8px; +} + +h4 { + font-size: 16px; + color: #303030; + font-weight: bold; +} + +h5 { + font-size: 1em; + color: #303030; +} + +h6 { + font-size: .8em; + color: #303030; +} + +p { + font-weight: 300; + margin-bottom: 20px; +} + +a { + text-decoration: none; +} + +p a { + font-weight: 400; +} + +blockquote { + font-size: 1.6em; + border-left: 10px solid #e9e9e9; + margin-bottom: 20px; + padding: 0 0 0 30px; +} + +ul li { + list-style: disc inside; + padding-left: 20px; +} + +ol li { + list-style: decimal inside; + padding-left: 3px; +} + +dl dd { + font-style: italic; + font-weight: 100; +} + +footer { + margin-top: 40px; + padding-top: 20px; + padding-bottom: 30px; + font-size: 13px; + color: #aaa; +} + +footer a { + color: #666; +} + +/* MISC */ +.clearfix:after { + clear: both; + content: '.'; + display: block; + visibility: hidden; + height: 0; +} + +.clearfix {display: inline-block;} +* html .clearfix {height: 1%;} +.clearfix {display: block;} \ No newline at end of file diff --git a/stylesheets/pygment_trac.css b/stylesheets/pygment_trac.css new file mode 100644 index 000000000..c6a6452d2 --- /dev/null +++ b/stylesheets/pygment_trac.css @@ -0,0 +1,69 @@ +.highlight { background: #ffffff; } +.highlight .c { color: #999988; font-style: italic } /* Comment */ +.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.highlight .k { font-weight: bold } /* Keyword */ +.highlight .o { font-weight: bold } /* Operator */ +.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ +.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #aa0000 } /* Generic.Error */ +.highlight .gh { color: #999999 } /* Generic.Heading */ +.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #555555 } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */ +.highlight .gt { color: #aa0000 } /* Generic.Traceback */ +.highlight .kc { font-weight: bold } /* Keyword.Constant */ +.highlight .kd { font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #009999 } /* Literal.Number */ +.highlight .s { color: #d14 } /* Literal.String */ +.highlight .na { color: #008080 } /* Name.Attribute */ +.highlight .nb { color: #0086B3 } /* Name.Builtin */ +.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */ +.highlight .no { color: #008080 } /* Name.Constant */ +.highlight .ni { color: #800080 } /* Name.Entity */ +.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */ +.highlight .nn { color: #555555 } /* Name.Namespace */ +.highlight .nt { color: #000080 } /* Name.Tag */ +.highlight .nv { color: #008080 } /* Name.Variable */ +.highlight .ow { font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #009999 } /* Literal.Number.Float */ +.highlight .mh { color: #009999 } /* Literal.Number.Hex */ +.highlight .mi { color: #009999 } /* Literal.Number.Integer */ +.highlight .mo { color: #009999 } /* Literal.Number.Oct */ +.highlight .sb { color: #d14 } /* Literal.String.Backtick */ +.highlight .sc { color: #d14 } /* Literal.String.Char */ +.highlight .sd { color: #d14 } /* Literal.String.Doc */ +.highlight .s2 { color: #d14 } /* Literal.String.Double */ +.highlight .se { color: #d14 } /* Literal.String.Escape */ +.highlight .sh { color: #d14 } /* Literal.String.Heredoc */ +.highlight .si { color: #d14 } /* Literal.String.Interpol */ +.highlight .sx { color: #d14 } /* Literal.String.Other */ +.highlight .sr { color: #009926 } /* Literal.String.Regex */ +.highlight .s1 { color: #d14 } /* Literal.String.Single */ +.highlight .ss { color: #990073 } /* Literal.String.Symbol */ +.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #008080 } /* Name.Variable.Class */ +.highlight .vg { color: #008080 } /* Name.Variable.Global */ +.highlight .vi { color: #008080 } /* Name.Variable.Instance */ +.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ + +.type-csharp .highlight .k { color: #0000FF } +.type-csharp .highlight .kt { color: #0000FF } +.type-csharp .highlight .nf { color: #000000; font-weight: normal } +.type-csharp .highlight .nc { color: #2B91AF } +.type-csharp .highlight .nn { color: #000000 } +.type-csharp .highlight .s { color: #A31515 } +.type-csharp .highlight .sc { color: #A31515 } diff --git a/stylesheets/stylesheet.css b/stylesheets/stylesheet.css new file mode 100644 index 000000000..020ad6dcc --- /dev/null +++ b/stylesheets/stylesheet.css @@ -0,0 +1,371 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} + +/* LAYOUT STYLES */ +body { + font-size: 1em; + line-height: 1.5; + background: #e7e7e7 url(../images/body-bg.png) 0 0 repeat; + font-family: 'Helvetica Neue', Helvetica, Arial, serif; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); + color: #6d6d6d; +} + +a { + color: #d5000d; +} +a:hover { + color: #c5000c; +} + +header { + padding-top: 35px; + padding-bottom: 25px; +} + +header h1 { + font-family: 'Chivo', 'Helvetica Neue', Helvetica, Arial, serif; font-weight: 900; + letter-spacing: -1px; + font-size: 48px; + color: #303030; + line-height: 1.2; +} + +header h2 { + letter-spacing: -1px; + font-size: 24px; + color: #aaa; + font-weight: normal; + line-height: 1.3; +} + +#container { + background: transparent url(../images/highlight-bg.jpg) 50% 0 no-repeat; + min-height: 595px; +} + +.inner { + width: 620px; + margin: 0 auto; +} + +#container .inner img { + max-width: 100%; +} + +#downloads { + margin-bottom: 40px; +} + +a.button { + -moz-border-radius: 30px; + -webkit-border-radius: 30px; + border-radius: 30px; + border-top: solid 1px #cbcbcb; + border-left: solid 1px #b7b7b7; + border-right: solid 1px #b7b7b7; + border-bottom: solid 1px #b3b3b3; + color: #303030; + line-height: 25px; + font-weight: bold; + font-size: 15px; + padding: 12px 8px 12px 8px; + display: block; + float: left; + width: 179px; + margin-right: 14px; + background: #fdfdfd; /* Old browsers */ + background: -moz-linear-gradient(top, #fdfdfd 0%, #f2f2f2 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fdfdfd), color-stop(100%,#f2f2f2)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #fdfdfd 0%,#f2f2f2 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #fdfdfd 0%,#f2f2f2 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #fdfdfd 0%,#f2f2f2 100%); /* IE10+ */ + background: linear-gradient(top, #fdfdfd 0%,#f2f2f2 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fdfdfd', endColorstr='#f2f2f2',GradientType=0 ); /* IE6-9 */ + -webkit-box-shadow: 10px 10px 5px #888; + -moz-box-shadow: 10px 10px 5px #888; + box-shadow: 0px 1px 5px #e8e8e8; +} +a.button:hover { + border-top: solid 1px #b7b7b7; + border-left: solid 1px #b3b3b3; + border-right: solid 1px #b3b3b3; + border-bottom: solid 1px #b3b3b3; + background: #fafafa; /* Old browsers */ + background: -moz-linear-gradient(top, #fdfdfd 0%, #f6f6f6 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fdfdfd), color-stop(100%,#f6f6f6)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #fdfdfd 0%,#f6f6f6 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #fdfdfd 0%,#f6f6f6 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #fdfdfd 0%,#f6f6f6 100%); /* IE10+ */ + background: linear-gradient(top, #fdfdfd 0%,#f6f6f6, 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fdfdfd', endColorstr='#f6f6f6',GradientType=0 ); /* IE6-9 */ +} + +a.button span { + padding-left: 50px; + display: block; + height: 23px; +} + +#download-zip span { + background: transparent url(../images/zip-icon.png) 12px 50% no-repeat; +} +#download-tar-gz span { + background: transparent url(../images/tar-gz-icon.png) 12px 50% no-repeat; +} +#view-on-github span { + background: transparent url(../images/octocat-icon.png) 12px 50% no-repeat; +} +#view-on-github { + margin-right: 0; +} + +code, pre { + font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; + color: #222; + margin-bottom: 30px; + font-size: 14px; +} + +code { + background-color: #f2f2f2; + border: solid 1px #ddd; + padding: 0 3px; +} + +pre { + padding: 20px; + background: #303030; + color: #f2f2f2; + text-shadow: none; + overflow: auto; +} +pre code { + color: #f2f2f2; + background-color: #303030; + border: none; + padding: 0; +} + +ul, ol, dl { + margin-bottom: 20px; +} + + +/* COMMON STYLES */ + +hr { + height: 1px; + line-height: 1px; + margin-top: 1em; + padding-bottom: 1em; + border: none; + background: transparent url('../images/hr.png') 50% 0 no-repeat; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +table { + width: 100%; + border: 1px solid #ebebeb; +} + +th { + font-weight: 500; +} + +td { + border: 1px solid #ebebeb; + text-align: center; + font-weight: 300; +} + +form { + background: #f2f2f2; + padding: 20px; + +} + + +/* GENERAL ELEMENT TYPE STYLES */ + +h1 { + font-size: 32px; +} + +h2 { + font-size: 22px; + font-weight: bold; + color: #303030; + margin-bottom: 8px; +} + +h3 { + color: #d5000d; + font-size: 18px; + font-weight: bold; + margin-bottom: 8px; +} + +h4 { + font-size: 16px; + color: #303030; + font-weight: bold; +} + +h5 { + font-size: 1em; + color: #303030; +} + +h6 { + font-size: .8em; + color: #303030; +} + +p { + font-weight: 300; + margin-bottom: 20px; +} + +a { + text-decoration: none; +} + +p a { + font-weight: 400; +} + +blockquote { + font-size: 1.6em; + border-left: 10px solid #e9e9e9; + margin-bottom: 20px; + padding: 0 0 0 30px; +} + +ul li { + list-style: disc inside; + padding-left: 20px; +} + +ol li { + list-style: decimal inside; + padding-left: 3px; +} + +dl dt { + color: #303030; +} + +footer { + background: transparent url('../images/hr.png') 0 0 no-repeat; + margin-top: 40px; + padding-top: 20px; + padding-bottom: 30px; + font-size: 13px; + color: #aaa; +} + +footer a { + color: #666; +} +footer a:hover { + color: #444; +} + +/* MISC */ +.clearfix:after { + clear: both; + content: '.'; + display: block; + visibility: hidden; + height: 0; +} + +.clearfix {display: inline-block;} +* html .clearfix {height: 1%;} +.clearfix {display: block;} + +/* #Media Queries +================================================== */ + +/* Smaller than standard 960 (devices and browsers) */ +@media only screen and (max-width: 959px) {} + +/* Tablet Portrait size to standard 960 (devices and browsers) */ +@media only screen and (min-width: 768px) and (max-width: 959px) {} + +/* All Mobile Sizes (devices and browser) */ +@media only screen and (max-width: 767px) { + header { + padding-top: 10px; + padding-bottom: 10px; + } + #downloads { + margin-bottom: 25px; + } + #download-zip, #download-tar-gz { + display: none; + } + .inner { + width: 94%; + margin: 0 auto; + } +} + +/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */ +@media only screen and (min-width: 480px) and (max-width: 767px) {} + +/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */ +@media only screen and (max-width: 479px) {}