/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.marketdata.availability; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.util.async.BlockingOperation; /** * Indicates that market data is available if any of the underlyings claim that it is. If none of the underlying claim availability, but at least one throws a {@link MarketDataNotSatisfiableException} * the market data is considered missing. Otherwise it is not available. * * @param <T> the component type */ public abstract class UnionMarketDataAvailability<T> { private final Collection<? extends T> _underlyings; /** * */ public static class Filter extends UnionMarketDataAvailability<MarketDataAvailabilityFilter> implements MarketDataAvailabilityFilter { public Filter(final Collection<? extends MarketDataAvailabilityFilter> underlyings) { super(underlyings); } @Override protected Object getAvailabilityImpl(final ComputationTargetSpecification targetSpec, final Object target, final ValueRequirement desiredValue, final MarketDataAvailabilityFilter underlying) { return underlying.isAvailable(targetSpec, target, desiredValue) ? Boolean.TRUE : null; } @Override public boolean isAvailable(final ComputationTargetSpecification targetSpec, final Object target, final ValueRequirement desiredValue) { return getAvailabilityImpl(targetSpec, target, desiredValue) != null; } @Override public MarketDataAvailabilityProvider withProvider(MarketDataAvailabilityProvider provider) { provider = AbstractMarketDataAvailabilityProvider.of(provider); final List<MarketDataAvailabilityProvider> union = new ArrayList<MarketDataAvailabilityProvider>(); for (final MarketDataAvailabilityFilter underlying : getUnderlyings()) { union.add(underlying.withProvider(provider)); } return new Provider(union); } } /** * */ public static class Provider extends UnionMarketDataAvailability<MarketDataAvailabilityProvider> implements MarketDataAvailabilityProvider { public Provider(final Collection<? extends MarketDataAvailabilityProvider> underlyings) { super(underlyings); } @Override protected Object getAvailabilityImpl(final ComputationTargetSpecification targetSpec, final Object target, final ValueRequirement desiredValue, final MarketDataAvailabilityProvider underlying) { return underlying.getAvailability(targetSpec, target, desiredValue); } @Override public ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final Object target, final ValueRequirement desiredValue) { return (ValueSpecification) getAvailabilityImpl(targetSpec, target, desiredValue); } @Override public MarketDataAvailabilityFilter getAvailabilityFilter() { final List<MarketDataAvailabilityFilter> union = new ArrayList<MarketDataAvailabilityFilter>(); for (final MarketDataAvailabilityProvider underlying : getUnderlyings()) { union.add(underlying.getAvailabilityFilter()); } return new Filter(union); } @Override public Serializable getAvailabilityHintKey() { final ArrayList<Serializable> key = new ArrayList<Serializable>(getUnderlyings().size()); for (MarketDataAvailabilityProvider underlying : getUnderlyings()) { key.add(underlying.getAvailabilityHintKey()); } return key; } } protected UnionMarketDataAvailability(final Collection<? extends T> underlyings) { _underlyings = underlyings; } protected Collection<? extends T> getUnderlyings() { return _underlyings; } protected abstract Object getAvailabilityImpl(ComputationTargetSpecification targetSpec, Object target, ValueRequirement desiredValue, T underlying); protected Object getAvailabilityImpl(final ComputationTargetSpecification targetSpec, final Object target, final ValueRequirement desiredValue) { MarketDataNotSatisfiableException missing = null; boolean failed = false; for (final T underlying : getUnderlyings()) { try { final Object v = getAvailabilityImpl(targetSpec, target, desiredValue, underlying); if (v != null) { return v; } } catch (final BlockingOperation e) { failed = true; } catch (final MarketDataNotSatisfiableException e) { missing = e; } } if (failed) { // Blocking mode is off, nothing declared AVAILABLE, and at least one wanted to block throw BlockingOperation.block(); } else { if (missing != null) { throw missing; } else { return null; } } } }