/**
* Copyright (c) 2012, 2014, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag.
*
* 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 org.javamoney.moneta;
import javax.money.CurrencyContext;
import javax.money.CurrencyContextBuilder;
import javax.money.CurrencyUnit;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Adapter that implements the new {@link CurrencyUnit} interface using the
* JDK's {@link Currency}.
*
* @author Anatole Tresch
* @author Werner Keil
* @version 0.5
*/
public final class TestCurrency implements CurrencyUnit, Serializable, Comparable<CurrencyUnit> {
/**
* The predefined name space for ISO 4217 currencies, similar to
* {@link Currency}.
*/
public 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<String, CurrencyUnit> CACHED = new ConcurrentHashMap<>();
private static final CurrencyContext CONTEXT =
CurrencyContextBuilder.of(TestCurrency.class.getSimpleName()).build();
/**
* Private constructor.
*
* @param code The (unique) currency code, not null-
* @param numCode the numeric code.
* @param fractionDigits the fraction digits to be used.
*/
private 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;
}
public String getCurrencyCode() {
return currencyCode;
}
public int getNumericCode() {
return numericCode;
}
public int getDefaultFractionDigits() {
return defaultFractionDigits;
}
@Override
public CurrencyContext getContext() {
return CONTEXT;
}
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) {
this.currencyCode = Optional.ofNullable(currencyCode)
.orElseThrow(() -> new IllegalArgumentException("currencyCode may not be null."));
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 CurrencyUnit} interface using the
* JDK's {@link Currency}.
* <p>
* 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<CurrencyUnit> {
/**
* 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 instance
*/
private JDKCurrencyAdapter(Currency currency) {
this.currency =
Optional.ofNullable(currency).orElseThrow(() -> new IllegalArgumentException("Currency required."));
}
@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;
}
public String getCurrencyCode() {
return this.currency.getCurrencyCode();
}
public int getNumericCode() {
return this.currency.getNumericCode();
}
public int getDefaultFractionDigits() {
return this.currency.getDefaultFractionDigits();
}
@Override
public CurrencyContext getContext() {
return CONTEXT;
}
public String toString() {
return this.currency.toString();
}
}
}