/*
* Copyright (c) 2012, 2013, Credit Suisse (Anatole Tresch), Werner Keil.
*
* 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.regions.internal;
import java.util.Collection;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import javax.inject.Singleton;
import javax.money.spi.Bootstrap;
import org.javamoney.regions.Region;
import org.javamoney.regions.RegionTreeNode;
import org.javamoney.regions.RegionType;
import org.javamoney.regions.spi.ExtendedRegionDataProviderSpi;
import org.javamoney.regions.spi.RegionProviderSpi;
import org.javamoney.regions.spi.RegionTreeProviderSpi;
import org.javamoney.regions.spi.RegionsSingletonSpi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class models the an internal service class, that provides the base
* method used by the {@link RegionsSingletonSpi} implementation. It is extended
* for different runtime scenarios, hereby allowing the spi implementation
* loaded using different mechanisms.
*
* @author Anatole Tresch
* @author Werner Keil
*/
@Singleton
public class DefaultRegionsSingleton implements RegionsSingletonSpi{
/** The logger used. */
private static final Logger LOG = LoggerFactory
.getLogger(DefaultRegionsSingleton.class);
/**
* Access a {@link Region} by {@link RegionType} and its numeric id.
*
* @param type
* The region's type
* @param numericId
* the region's numeric id
* @return the region found, never {@code null}
* @throws IllegalArgumentException
* , if no such region could be found.
*/
@Override
public Region getRegion(RegionType type, int numericId) {
for (RegionProviderSpi prov : Bootstrap.getServices(RegionProviderSpi.class)) {
Region reg = prov.getRegion(type, numericId);
if (reg != null) {
return reg;
}
}
throw new IllegalArgumentException("So such reagion " + type + ':'
+ numericId);
}
/**
* Access a {@link Region} by {@link RegionType} and its textual id.
*
* @param type
* The region's type
* @param code
* the region's textual id
* @return the region found, never {@code null}
* @throws IllegalArgumentException
* , if no such region could be found.
*/
@Override
public Region getRegion(RegionType type, String code) {
for (RegionProviderSpi prov : Bootstrap.getServices(RegionProviderSpi.class)) {
Region reg = prov.getRegion(type, code);
if (reg != null) {
return reg;
}
}
throw new IllegalArgumentException("So such reagion " + type + ':'
+ code);
}
/**
* Get all {@link RegionType} instances that are known.
*
* @see RegionProviderSpi#getRegionTypes()
* @return the {@link RegionType} instances defined by the registered
* {@link RegionProviderSpi} instances.
*/
@Override
public Set<RegionType> getRegionTypes() {
Set<RegionType> result = new HashSet<RegionType>();
for (RegionProviderSpi prov : Bootstrap.getServices(RegionProviderSpi.class)) {
Collection<RegionType> regionTypes = prov.getRegionTypes();
if (regionTypes == null || regionTypes.isEmpty()) {
LOG.warn("Provider did not provide any regions: "
+ prov.getClass().getName());
} else {
result.addAll(regionTypes);
}
}
return result;
}
/**
* Get all {@link Region} instances of a given {@link RegionType}.
*
* @param type
* the region's type
* @return all {@link Region} instances with the given type.
*/
@Override
public Collection<Region> getRegions(RegionType type) {
Set<Region> result = new HashSet<Region>();
for (RegionProviderSpi prov : Bootstrap.getServices(RegionProviderSpi.class)) {
Collection<Region> regions = prov.getRegions(type);
if (regions == null || regions.isEmpty()) {
LOG.warn("Provider did not provide any regions: "
+ prov.getClass().getName());
} else {
result.addAll(regions);
}
}
return result;
}
/**
* Get the region by its locale.
*
* @param locale
* The locale
* @return the region found, or {@code null}
*/
@Override
public Region getRegion(Locale locale) {
for (RegionProviderSpi prov : Bootstrap.getServices(RegionProviderSpi.class)) {
Region region = prov.getRegion(locale);
if (region != null) {
return region;
}
}
return null;
}
/**
* Access a set of Region instances that are defined to be graph root
* regions, which are identifiable entry points into the region graph.
*
* @return the root graph {@link Region}s defined by this spi, not null.
*/
@Override
public RegionTreeNode getRegionTree(String treeId) {
for (RegionTreeProviderSpi prov : Bootstrap.getServices(RegionTreeProviderSpi.class)) {
try {
if (treeId.equals(prov.getTreeId())) {
RegionTreeNode node = prov.getRegionTree();
if (node == null) {
LOG.error("Error accessing RegionTree: " + treeId
+ " from " + prov.getClass().getName()
+ ": provider returned null.");
return null;
}
return node;
}
} catch (Exception e) {
LOG.error("Error initializing RegionTreeProviderSpi: "
+ prov.getClass().getName(), e);
}
}
return null;
}
/**
* Access all regions.
*
* @return the regions found, never null.
*/
private Collection<Region> getAllRegions() {
Set<Region> result = new HashSet<Region>();
for (RegionProviderSpi prov : Bootstrap.getServices(RegionProviderSpi.class)) {
Collection<RegionType> types = prov.getRegionTypes();
for (RegionType t : types) {
Collection<Region> regions = prov.getRegions(t);
if (regions == null || regions.isEmpty()) {
LOG.warn("Provider did not provide any regions: "
+ prov.getClass().getName());
} else {
result.addAll(regions);
}
}
}
return result;
}
@Override
public Collection<Class> getExtendedRegionDataTypes(Region region) {
Set<Class> result = new HashSet<>();
for(ExtendedRegionDataProviderSpi spi: Bootstrap.getServices(ExtendedRegionDataProviderSpi.class)){
result.addAll(spi.getExtendedRegionDataTypes(region));
}
return result;
}
@Override
public <T> T getExtendedRegionData(Region region, Class<T> type) {
for(ExtendedRegionDataProviderSpi spi: Bootstrap.getServices(ExtendedRegionDataProviderSpi.class)){
if(spi.getExtendedRegionDataTypes(region).contains(type)){
return spi.getExtendedRegionData(region, type);
}
}
return null;
}
@Override
public Set<String> getRegionTreeIds() {
Set<String> result = new HashSet<>();
for (RegionTreeProviderSpi prov : Bootstrap.getServices(RegionTreeProviderSpi.class)) {
try {
result.add(prov.getTreeId());
} catch (Exception e) {
LOG.error("Error accessing RegionTreeProviderSpi: "
+ prov.getClass().getName(), e);
}
}
return result;
}
}