/*
* 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 MonetaryOperator
.
This class is thread-safe.
Author: Anatole Tresch, Werner Keil
/**
* This class models the accessor for rounding instances, modeled as
* {@link javax.money.MonetaryOperator}.
* <p>
* 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.
/**
* An adaptive rounding instance that transparently looks up the correct
* rounding.
*/
private static final MonetaryRounding DEFAULT_ROUNDING = new DefaultCurrencyRounding();
Creates an rounding instance using RoundingMode.UP
rounding. Throws: - MonetaryException – if no such rounding could be evaluated.
Returns: the corresponding MonetaryOperator
implementing the rounding.
/**
* 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.
Returns: the default rounding, never null.
/**
* 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 RoundingQuery
. Params: - query – the rounding query, not null.
Returns: the collection found, not null.
/**
* Query all roundings matching the given {@link RoundingQuery}.
*
* @param query the rounding query, not null.
* @return the collection found, not null.
*/
@Override
public Collection<MonetaryRounding> getRoundings(RoundingQuery query) {
List<MonetaryRounding> result = new ArrayList<>();
Collection<String> 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.
Returns: the names of all current registered providers, never null.
/**
* Get the names of all current registered providers.
*
* @return the names of all current registered providers, never null.
*/
@Override
public Set<String> getProviderNames() {
Set<String> 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.
Returns: the default provider list and ordering, not null.
/**
* Get the default providers list to be used.
*
* @return the default provider list and ordering, not null.
*/
@Override
public List<String> getDefaultProviderChain() {
List<String> result = new ArrayList<>(Monetary.getRoundingProviderNames());
Collections.sort(result);
return result;
}
Allows to access the identifiers of the current defined roundings.
Params: - providers – the providers and ordering to be used. By default providers and ordering as defined in
#getDefaultProviders is used, not null.
Returns: the set of custom rounding ids, never null
.
/**
* 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<String> getRoundingNames(String... providers) {
Set<String> 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 MonetaryAmount
based on the amount's CurrencyUnit
. Author: Anatole Tresch
/**
* 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;
}
}
}