/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.security.lookup;
import java.util.Map;
import org.joda.beans.Bean;
import org.joda.beans.MetaProperty;
import com.google.common.collect.Maps;
import com.opengamma.core.security.Security;
import com.opengamma.master.security.ManageableSecurity;
import com.opengamma.util.ArgumentChecker;
/**
* Maps the properties of {@link SecurityAttribute} to properties in each supported security type.
*/
@SuppressWarnings({"unchecked", "rawtypes" })
public class SecurityAttributeMapper {
/** Value providers for the blotter columns, keyed by the type of object being displayed in the blotter. */
private final Map<Class<?>, Map<SecurityAttribute, SecurityValueProvider>> _mappings = Maps.newHashMap();
/* package */ SecurityAttributeMapper() {
}
/* package */ void mapColumn(SecurityAttribute column, MetaProperty<?> metaProp) {
ArgumentChecker.notNull(column, "column");
ArgumentChecker.notNull(metaProp, "metaProp");
Class<? extends ManageableSecurity> securityType = (Class<? extends ManageableSecurity>) metaProp.metaBean().beanType();
Map<SecurityAttribute, SecurityValueProvider> mappings = mappingsFor(securityType);
mappings.put(column, propertyProvider(metaProp));
}
/* package */ <T extends ManageableSecurity> void mapColumn(SecurityAttribute column,
Class<T> type,
SecurityValueProvider<T> provider) {
ArgumentChecker.notNull(column, "column");
ArgumentChecker.notNull(type, "type");
ArgumentChecker.notNull(provider, "provider");
Map<SecurityAttribute, SecurityValueProvider> mappings = mappingsFor(type);
mappings.put(column, provider);
}
/* package */ <T extends ManageableSecurity> void mapColumn(SecurityAttribute column, Class<T> type, String value) {
ArgumentChecker.notNull(column, "column");
ArgumentChecker.notNull(type, "type");
ArgumentChecker.notNull(value, "value");
Map<SecurityAttribute, SecurityValueProvider> mappings = mappingsFor(type);
mappings.put(column, new StaticValueProvider(value));
}
private <T extends ManageableSecurity> Map<SecurityAttribute, SecurityValueProvider> mappingsFor(Class<T> type) {
Map<SecurityAttribute, SecurityValueProvider> securityMappings = _mappings.get(type);
if (securityMappings != null) {
return securityMappings;
} else {
Map<SecurityAttribute, SecurityValueProvider> newMappings = Maps.newHashMap();
_mappings.put(type, newMappings);
return newMappings;
}
}
private SecurityValueProvider propertyProvider(MetaProperty<?> property) {
ArgumentChecker.notNull(property, "property");
return new PropertyValueProvider(property);
}
/**
* Returns the value to display for a security in a blotter column.
* @param column The blotter column
* @param security The security, possibly null (for rows that represent a portfolio node)
* @return The value to display in the column, not null
*/
public Object valueFor(SecurityAttribute column, Object security) {
// position rows have no security
if (security == null) {
return "";
}
return getValue(column, security, security.getClass());
}
private Object getValue(SecurityAttribute column, Object security, Class<?> type) {
Map<SecurityAttribute, SecurityValueProvider> providerMap = getMappingsForType(type);
if (providerMap == null) {
return "";
} else {
SecurityValueProvider valueProvider = providerMap.get(column);
if (valueProvider != null) {
return valueProvider.getValue(security);
} else {
Class<?> superclass = type.getSuperclass();
if (superclass == null) {
return "";
} else {
return getValue(column, security, superclass);
}
}
}
}
private Map<SecurityAttribute, SecurityValueProvider> getMappingsForType(Class<?> type) {
Map<SecurityAttribute, SecurityValueProvider> providerMap = _mappings.get(type);
if (providerMap != null) {
return providerMap;
} else {
Class<?> superclass = type.getSuperclass();
if (superclass == null) {
return null;
} else {
return getMappingsForType(superclass);
}
}
}
/**
* Looks up and returns values from {@link Bean} instances using a {@link MetaProperty}.
* @param <T>
*/
private static final class PropertyValueProvider<T extends Security> implements SecurityValueProvider<T> {
/** The property used to get the value from the security. */
private final MetaProperty<?> _property;
private PropertyValueProvider(MetaProperty<?> property) {
ArgumentChecker.notNull(property, "property");
_property = property;
}
@Override
public Object getValue(T security) {
return _property.get((Bean) security);
}
}
/**
* Provides a fixed value for a cell.
*/
private static final class StaticValueProvider implements SecurityValueProvider {
/** The value that is always returned from {@link #getValue} */
private final Object _value;
private StaticValueProvider(Object value) {
ArgumentChecker.notNull(value, "value");
_value = value;
}
@Override
public Object getValue(Object security) {
return _value;
}
}
}