/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.marketdata.snapshot;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.core.marketdatasnapshot.MarketDataSnapshotChangeListener;
import com.opengamma.core.marketdatasnapshot.MarketDataSnapshotSource;
import com.opengamma.core.marketdatasnapshot.StructuredMarketDataSnapshot;
import com.opengamma.engine.marketdata.AbstractMarketDataProvider;
import com.opengamma.engine.marketdata.MarketDataListener;
import com.opengamma.engine.marketdata.MarketDataPermissionProvider;
import com.opengamma.engine.marketdata.MarketDataProvider;
import com.opengamma.engine.marketdata.MarketDataSnapshot;
import com.opengamma.engine.marketdata.PermissiveMarketDataPermissionProvider;
import com.opengamma.engine.marketdata.availability.MarketDataAvailabilityProvider;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.marketdata.spec.UserMarketDataSpecification;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.util.ArgumentChecker;
/**
* Implementation of {@link MarketDataProvider} which sources its data from user-generated snapshots from a {@link MarketDataSnapshotSource}.
*/
public class UserMarketDataProvider extends AbstractMarketDataProvider {
private final MarketDataSnapshotSource _snapshotSource;
private final UniqueId _snapshotId;
private final CopyOnWriteArraySet<ValueSpecification> _listeningValueSpecifications = new CopyOnWriteArraySet<ValueSpecification>();
private final MarketDataPermissionProvider _permissionProvider;
private final MarketDataSnapshotChangeListener _snapshotSourceChangeListener;
private final Object _listenerLock = new Object();
private final Object _initSnapshotLock = new Object();
private volatile UserMarketDataSnapshot _snapshot;
public UserMarketDataProvider(final MarketDataSnapshotSource snapshotSource, final UniqueId snapshotId) {
ArgumentChecker.notNull(snapshotSource, "snapshotSource");
ArgumentChecker.notNull(snapshotId, "snapshotId");
_snapshotSource = snapshotSource;
_snapshotId = snapshotId;
// Assume no permission issues
_permissionProvider = new PermissiveMarketDataPermissionProvider();
_snapshotSourceChangeListener = new MarketDataSnapshotChangeListener() {
@Override
public void objectChanged(ObjectId oid) {
if (!oid.equals(getSnapshotId().getObjectId())) {
return;
}
synchronized (_initSnapshotLock) {
_snapshot = null;
}
valuesChanged(_listeningValueSpecifications);
}
};
}
private UserMarketDataSnapshot getSnapshot() {
UserMarketDataSnapshot snapshot = _snapshot;
if (snapshot != null) {
return snapshot;
}
synchronized (_initSnapshotLock) {
if (_snapshot == null) {
StructuredMarketDataSnapshot structuredSnapshot = (StructuredMarketDataSnapshot) getSnapshotSource().get(getSnapshotId());
snapshot = new UserMarketDataSnapshot(structuredSnapshot);
snapshot.init();
_snapshot = snapshot;
}
return _snapshot;
}
}
//-------------------------------------------------------------------------
@Override
public void addListener(final MarketDataListener listener) {
synchronized (_listenerLock) {
if (getListeners().size() == 0) {
_snapshotSource.addChangeListener(_snapshotId, _snapshotSourceChangeListener);
}
super.addListener(listener);
}
}
@Override
public void removeListener(final MarketDataListener listener) {
synchronized (_listenerLock) {
super.removeListener(listener);
if (getListeners().size() == 0) {
_snapshotSource.removeChangeListener(_snapshotId, _snapshotSourceChangeListener);
}
}
}
//-------------------------------------------------------------------------
@Override
public void subscribe(final ValueSpecification valueSpecification) {
subscribe(Collections.singleton(valueSpecification));
}
@Override
public void subscribe(final Set<ValueSpecification> valueSpecifications) {
_listeningValueSpecifications.addAll(valueSpecifications);
subscriptionsSucceeded(valueSpecifications);
}
@Override
public void unsubscribe(final ValueSpecification valueSpecification) {
unsubscribe(Collections.singleton(valueSpecification));
}
@Override
public void unsubscribe(final Set<ValueSpecification> valueSpecifications) {
// TODO
}
//-------------------------------------------------------------------------
@Override
public MarketDataAvailabilityProvider getAvailabilityProvider(final MarketDataSpecification marketDataSpec) {
return getSnapshot().getAvailabilityProvider();
}
@Override
public MarketDataPermissionProvider getPermissionProvider() {
return _permissionProvider;
}
//-------------------------------------------------------------------------
@Override
public boolean isCompatible(final MarketDataSpecification marketDataSpec) {
if (!(marketDataSpec instanceof UserMarketDataSpecification)) {
return false;
}
final UserMarketDataSpecification userMarketDataSpec = (UserMarketDataSpecification) marketDataSpec;
return getSnapshotId().equals(userMarketDataSpec.getUserSnapshotId());
}
@Override
public MarketDataSnapshot snapshot(MarketDataSpecification marketDataSpec) {
if (!isCompatible(marketDataSpec)) {
throw new OpenGammaRuntimeException("Market data specification " + marketDataSpec + " is incompatible with " +
UserMarketDataProvider.class.getSimpleName() + " for snapshot " + getSnapshotId());
}
return getSnapshot();
}
private UniqueId getSnapshotId() {
return _snapshotId;
}
private MarketDataSnapshotSource getSnapshotSource() {
return _snapshotSource;
}
}