001/** 002 * Copyright (c) 2012, 2014, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016package org.javamoney.moneta.internal; 017 018import org.javamoney.moneta.spi.base.BaseMonetaryAmountsSingletonSpi; 019 020import javax.money.MonetaryAmount; 021import javax.money.MonetaryAmountFactory; 022import javax.money.MonetaryException; 023import javax.money.spi.Bootstrap; 024import javax.money.spi.MonetaryAmountFactoryProviderSpi; 025 026import java.util.Map; 027import java.util.Set; 028import java.util.concurrent.ConcurrentHashMap; 029 030/** 031 * Default implementation ot {@link javax.money.spi.MonetaryAmountsSingletonSpi} loading the SPIs on startup 032 * initially once, using the 033 * JSR's {@link javax.money.spi.Bootstrap} mechanism. 034 */ 035public class DefaultMonetaryAmountsSingletonSpi extends BaseMonetaryAmountsSingletonSpi { 036 037 private final Map<Class<? extends MonetaryAmount>, MonetaryAmountFactoryProviderSpi<?>> factories = 038 new ConcurrentHashMap<>(); 039 040 private Class<? extends MonetaryAmount> configuredDefaultAmountType = loadDefaultAmountType(); 041 042 public DefaultMonetaryAmountsSingletonSpi() { 043 for (MonetaryAmountFactoryProviderSpi<?> f : Bootstrap.getServices(MonetaryAmountFactoryProviderSpi.class)) { 044 MonetaryAmountFactoryProviderSpi<?> factory = factories.get(f.getAmountType()); 045 if(factory==null){ 046 factories.put(f.getAmountType(), f); 047 } 048 } 049 } 050 051 /** 052 * Tries to load the default {@link MonetaryAmount} class from 053 * {@code javamoney.properties} with contents as follows:<br/> 054 * <code> 055 * org.javamoney.bp.defaults.amount.class=my.fully.qualified.ClassName 056 * </code> 057 * 058 * @return the loaded default class, or {@code null} 059 */ 060 // type check should be safe, exception will be logged if not. 061 private Class<? extends MonetaryAmount> loadDefaultAmountType() { 062 return null; 063 } 064 065 066 // save cast, since members are managed by this instance 067 @SuppressWarnings("unchecked") 068 @Override 069 public <T extends MonetaryAmount> MonetaryAmountFactory<T> getAmountFactory(Class<T> amountType) { 070 MonetaryAmountFactoryProviderSpi<T> f = MonetaryAmountFactoryProviderSpi.class.cast(factories.get(amountType)); 071 if (f!=null) { 072 return f.createMonetaryAmountFactory(); 073 } 074 throw new MonetaryException("No matching MonetaryAmountFactory found, type=" + amountType.getName()); 075 } 076 077 @Override 078 public Set<Class<? extends MonetaryAmount>> getAmountTypes() { 079 return factories.keySet(); 080 } 081 082 /* 083 * (non-Javadoc) 084 * 085 * @see org.javamoney.bp.api.spi.MonetaryAmountsSpi#getDefaultAmountType() 086 */ 087 @Override 088 public Class<? extends MonetaryAmount> getDefaultAmountType() { 089 if (configuredDefaultAmountType==null) { 090 for (MonetaryAmountFactoryProviderSpi<?> f : Bootstrap.getServices(MonetaryAmountFactoryProviderSpi.class)) { 091 if (f.getQueryInclusionPolicy() == MonetaryAmountFactoryProviderSpi.QueryInclusionPolicy.ALWAYS) { 092 configuredDefaultAmountType = f.getAmountType(); 093 break; 094 } 095 } 096 } 097 if(configuredDefaultAmountType==null){ 098 throw new MonetaryException("No MonetaryAmountFactoryProviderSpi registered."); 099 } 100 return configuredDefaultAmountType; 101 } 102 103}