/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.marketdata; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import org.threeten.bp.Duration; import org.threeten.bp.Instant; import com.opengamma.engine.marketdata.availability.MarketDataAvailabilityProvider; import com.opengamma.engine.marketdata.spec.MarketDataSpecification; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.util.ArgumentChecker; /** * Combines a {@link MarketDataProvider} with another which provides overrides. */ public class MarketDataProviderWithOverride implements MarketDataProvider { private final MarketDataProvider _underlying; private final MarketDataInjectorImpl _override; private final Set<MarketDataListener> _listeners = new CopyOnWriteArraySet<MarketDataListener>(); private final Set<ValueSpecification> _pendingSubscriptions = new HashSet<ValueSpecification>(); private boolean _listenerAttached; private final MarketDataListener _listener = new MarketDataListener() { @Override public void subscriptionsSucceeded(Collection<ValueSpecification> specifications) { MarketDataProviderWithOverride.this.subscriptionsSucceeded(specifications); } @Override public void subscriptionFailed(ValueSpecification specification, String msg) { MarketDataProviderWithOverride.this.subscriptionFailed(specification, msg); } @Override public void subscriptionStopped(ValueSpecification specification) { MarketDataProviderWithOverride.this.subscriptionStopped(specification); } @Override public void valuesChanged(Collection<ValueSpecification> specifications) { MarketDataProviderWithOverride.this.valuesChanged(specifications); } }; /** * Constructs an instance using the specified providers. * * @param underlying the underlying, or default, provider, not null * @param override the override provider, not null */ public MarketDataProviderWithOverride(final MarketDataProvider underlying, final MarketDataInjectorImpl override) { ArgumentChecker.notNull(underlying, "underlying"); ArgumentChecker.notNull(override, "override"); _underlying = underlying; _override = override; } //-------------------------------------------------------------------------- @Override public void addListener(final MarketDataListener listener) { _listeners.add(listener); checkListenerAttach(); } @Override public void removeListener(final MarketDataListener listener) { _listeners.remove(listener); checkListenerAttach(); } private void checkListenerAttach() { synchronized (_listener) { final boolean anyListeners = _listeners.size() > 0; if (anyListeners && !_listenerAttached) { _underlying.addListener(_listener); _listenerAttached = true; } else if (!anyListeners && _listenerAttached) { _underlying.removeListener(_listener); _listenerAttached = false; } } } //------------------------------------------------------------------------- @Override public void subscribe(final ValueSpecification valueSpecification) { _pendingSubscriptions.add(valueSpecification); _underlying.subscribe(valueSpecification); } @Override public void subscribe(final Set<ValueSpecification> valueSpecifications) { _pendingSubscriptions.addAll(valueSpecifications); _underlying.subscribe(valueSpecifications); } @Override public void unsubscribe(final ValueSpecification valueSpecification) { _underlying.unsubscribe(valueSpecification); } @Override public void unsubscribe(final Set<ValueSpecification> valueSpecifications) { _underlying.unsubscribe(valueSpecifications); } //------------------------------------------------------------------------- @Override public MarketDataAvailabilityProvider getAvailabilityProvider(final MarketDataSpecification marketDataSpec) { // Assume overrides only valid if data available from underlying return _underlying.getAvailabilityProvider(marketDataSpec); } @Override public MarketDataPermissionProvider getPermissionProvider() { // Assume overrides not permissioned return _underlying.getPermissionProvider(); } //------------------------------------------------------------------------- @Override public boolean isCompatible(final MarketDataSpecification marketDataSpec) { return _underlying.isCompatible(marketDataSpec); } @Override public MarketDataSnapshot snapshot(final MarketDataSpecification marketDataSpec) { final MarketDataSnapshot underlyingSnapshot = _underlying.snapshot(marketDataSpec); final MarketDataInjectorImpl.Snapshot overrideSnapshot = _override.snapshot(getAvailabilityProvider(marketDataSpec)); return new MarketDataSnapshotWithOverride(underlyingSnapshot, overrideSnapshot); } @Override public Duration getRealTimeDuration(final Instant fromInstant, final Instant toInstant) { return _underlying.getRealTimeDuration(fromInstant, toInstant); } //-------------------------------------------------------------------------- private void subscriptionsSucceeded(final Collection<ValueSpecification> specifications) { for (final MarketDataListener listener : _listeners) { listener.subscriptionsSucceeded(specifications); } } private void subscriptionFailed(final ValueSpecification specification, final String msg) { for (final MarketDataListener listener : _listeners) { listener.subscriptionFailed(specification, msg); } } private void subscriptionStopped(final ValueSpecification specification) { for (final MarketDataListener listener : _listeners) { listener.subscriptionStopped(specification); } } private void valuesChanged(final Collection<ValueSpecification> specifications) { for (final MarketDataListener listener : _listeners) { listener.valuesChanged(specifications); } } }