/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.aggregation;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
import com.opengamma.core.exchange.Exchange;
import com.opengamma.core.exchange.ExchangeSource;
import com.opengamma.core.position.Position;
import com.opengamma.core.position.impl.SimplePositionComparator;
import com.opengamma.core.region.Region;
import com.opengamma.core.region.RegionSource;
import com.opengamma.core.security.Security;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.financial.security.FinancialSecurityUtils;
import com.opengamma.id.ExternalId;
import com.opengamma.id.UniqueId;
import com.opengamma.util.CompareUtils;
/**
* Function to classify positions by Currency.
*
*/
public class RegionAggregationFunction implements AggregationFunction<String> {
private boolean _useAttributes;
private boolean _includeEmptyCategories;
private static final Logger s_logger = LoggerFactory.getLogger(RegionAggregationFunction.class);
private static final String NAME = "Region";
private static final String OTHER = "Other";
private static final String NO_REGION = "N/A";
private static final List<String> s_topLevelRegions = Arrays.asList("Africa", "Asia", "South America", "Europe");
private static final List<String> s_specialCountriesRegions = Arrays.asList("United States", "Canada");
private static final List<String> s_requiredEntries = Lists.newArrayList();
static {
s_requiredEntries.addAll(s_topLevelRegions);
s_requiredEntries.addAll(s_specialCountriesRegions);
s_requiredEntries.add(OTHER);
s_requiredEntries.add(NO_REGION);
}
private SecuritySource _secSource;
private RegionSource _regionSource;
private ExchangeSource _exchangeSource;
private final Comparator<Position> _comparator = new SimplePositionComparator();
public RegionAggregationFunction(SecuritySource secSource, RegionSource regionSource, ExchangeSource exchangeSource) {
this(secSource, regionSource, exchangeSource, false);
}
public RegionAggregationFunction(SecuritySource secSource, RegionSource regionSource, ExchangeSource exchangeSource, boolean useAttributes) {
this(secSource, regionSource, exchangeSource, useAttributes, true);
}
public RegionAggregationFunction(SecuritySource secSource, RegionSource regionSource, ExchangeSource exchangeSource, boolean useAttributes, boolean includeEmptyCategories) {
_secSource = secSource;
_regionSource = regionSource;
_exchangeSource = exchangeSource;
_useAttributes = useAttributes;
_includeEmptyCategories = includeEmptyCategories;
}
/**
* Can use this when no RegionSource available and will get the ISO code instead of the pretty string.
*/
public RegionAggregationFunction() {
_regionSource = null;
_exchangeSource = null;
}
@Override
public String classifyPosition(Position position) {
if (_useAttributes) {
Map<String, String> attributes = position.getAttributes();
s_logger.warn("attributes on " + position + " = " + attributes.entrySet());
if (attributes.containsKey(getName())) {
return attributes.get(getName());
} else {
return NO_REGION;
}
} else {
try {
Security security = position.getSecurityLink().getTarget();
if (security == null) {
security = position.getSecurityLink().resolve(_secSource);
}
ExternalId id = FinancialSecurityUtils.getRegion(security);
if (_regionSource != null) {
if (id != null) {
Region highestLevelRegion = _regionSource.getHighestLevelRegion(id);
if (highestLevelRegion != null) {
return highestLevelRegion.getName();
} else {
return id.getValue();
}
} else if (_exchangeSource != null) {
ExternalId exchangeId = FinancialSecurityUtils.getExchange(security);
if (exchangeId != null) {
Exchange exchange = _exchangeSource.getSingle(exchangeId);
if (exchange == null) {
s_logger.info("No exchange could be found with ID {}", exchangeId);
return NO_REGION;
}
if (exchange.getRegionIdBundle() == null) {
s_logger.info("Exchange " + exchange.getName() + " region bundle was null");
return NO_REGION;
}
Region highestLevelRegion = _regionSource.getHighestLevelRegion(exchange.getRegionIdBundle());
if (s_specialCountriesRegions.contains(highestLevelRegion.getName())) {
return highestLevelRegion.getName();
} else {
Set<UniqueId> parentRegionIds = highestLevelRegion.getParentRegionIds();
s_logger.info("got " + highestLevelRegion + ", looking for parent");
String parent = findTopLevelRegion(parentRegionIds);
s_logger.info("parent was " + parent);
return parent;
}
}
}
return NO_REGION;
} else {
if (id != null) {
return id.getValue();
} else {
return NO_REGION;
}
}
} catch (UnsupportedOperationException ex) {
return NO_REGION;
}
}
}
private String findTopLevelRegion(Set<?> parentRegions) {
for (Object parentRegion : parentRegions) {
Region region;
if (parentRegion instanceof String) {
region = _regionSource.get(UniqueId.parse((String) parentRegion));
} else {
region = _regionSource.get((UniqueId) parentRegion);
}
if (region != null) {
if (s_topLevelRegions.contains(region.getName())) {
return region.getName();
}
}
}
return OTHER;
}
public String getName() {
return NAME;
}
@Override
public Collection<String> getRequiredEntries() {
if (_includeEmptyCategories) {
return s_requiredEntries;
} else {
return Collections.emptyList();
}
}
@Override
public int compare(String o1, String o2) {
return CompareUtils.compareByList(s_requiredEntries, o1, o2);
}
@Override
public Comparator<Position> getPositionComparator() {
return _comparator;
}
}