com.opengamma.engine.view.calc.CompositeMarketDataSnapshot.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.engine.view.calc.CompositeMarketDataSnapshot.java

Source

/**
 * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.engine.view.calc;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.time.Instant;

import com.google.common.base.Supplier;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.opengamma.engine.marketdata.MarketDataSnapshot;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.id.UniqueId;
import com.opengamma.util.ArgumentChecker;

/**
 * Snapshot of market data which aggregates data from multiple underlying snapshots.
 */
/* package */ class CompositeMarketDataSnapshot implements MarketDataSnapshot {

    /** The underlying snapshots. */
    private final List<MarketDataSnapshot> _snapshots;
    /** Supplies the current set of subscriptions for the underlying snapshots in the same order as the snapshots. */
    private final Supplier<List<Set<ValueRequirement>>> _subscriptionSupplier;

    /**
     * @param snapshots The underlying snapshots
     * @param subscriptionSupplier Supplies the current set of subscriptions for the underlying snapshots
     * in the same order as the snapshots. This snapshot is created before subscriptions are set up but the subscriptions
     * are available by the time this snapshot needs to use them. So the subscriptions must be requested from the
     * supplier when they're required.
     */
    /* package */ CompositeMarketDataSnapshot(List<MarketDataSnapshot> snapshots,
            Supplier<List<Set<ValueRequirement>>> subscriptionSupplier) {
        ArgumentChecker.notEmpty(snapshots, "snapshots");
        ArgumentChecker.notNull(subscriptionSupplier, "subscriptionSupplier");
        _subscriptionSupplier = subscriptionSupplier;
        _snapshots = snapshots;
    }

    @Override
    public UniqueId getUniqueId() {
        // TODO is this unique enough? same as in the existing impls
        return UniqueId.of(MARKET_DATA_SNAPSHOT_ID_SCHEME, "CompositeMarketDataSnapshot:" + getSnapshotTime());
    }

    /**
     * @return The first non-null indication of snapshot time from the underlying snapshots
     * @throws IllegalStateException If none of the underlying snapshots return a value
     */
    @Override
    public Instant getSnapshotTimeIndication() {
        for (MarketDataSnapshot snapshot : _snapshots) {
            Instant snapshotTimeIndication = snapshot.getSnapshotTimeIndication();
            if (snapshotTimeIndication != null) {
                return snapshotTimeIndication;
            }
        }
        throw new IllegalStateException("None of the underlying snapshots returned a snapshot time indication");
    }

    /**
     * Initializes all of the underlying snapshots.
     */
    @Override
    public void init() {
        for (MarketDataSnapshot snapshot : _snapshots) {
            snapshot.init();
        }
    }

    /**
     * Initializes the underlying snapshots.
     * @param requirements  the values required in the snapshot, not null
     * @param timeout  the maximum time to wait for the required values
     * @param unit  the timeout unit, not null
     */
    @Override
    public void init(Set<ValueRequirement> requirements, long timeout, TimeUnit unit) {
        ArgumentChecker.notNull(requirements, "requirements");
        ArgumentChecker.notNull(unit, "unit");
        List<Set<ValueRequirement>> subscriptions = _subscriptionSupplier.get();
        for (int i = 0; i < _snapshots.size(); i++) {
            MarketDataSnapshot snapshot = _snapshots.get(i);
            Set<ValueRequirement> snapshotSubscriptions = subscriptions.get(i);
            // TODO whole timeout? or divide timeout between all delegate snapshots and keep track of how much is left?
            // the combined snapshot does this but that seems broken to me
            Set<ValueRequirement> snapshotRequirements = Sets.intersection(snapshotSubscriptions, requirements);
            if (snapshotRequirements.isEmpty()) {
                snapshot.init();
            } else {
                snapshot.init(snapshotSubscriptions, timeout, unit);
            }
        }
    }

    /**
     * @return The first non-null snapshot time from the underlying snapshots
     * @throws IllegalStateException If none of the underlying snapshots return a value
     */
    @Override
    public Instant getSnapshotTime() {
        for (MarketDataSnapshot snapshot : _snapshots) {
            Instant snapshotTime = snapshot.getSnapshotTime();
            if (snapshotTime != null) {
                return snapshotTime;
            }
        }
        throw new IllegalStateException("None of the underlying snapshots returned a snapshot time");
    }

    /**
     * Returns the value from one of the underlying snapshots or null if it isn't available in any of them
     * @param requirement  the value required, not null
     * @return The value from one of the underlying snapshots or null if it isn't available in any of them
     */
    @Override
    public ComputedValue query(ValueRequirement requirement) {
        ArgumentChecker.notNull(requirement, "requirement");
        List<Set<ValueRequirement>> subscriptions = _subscriptionSupplier.get();
        for (int i = 0; i < _snapshots.size(); i++) {
            MarketDataSnapshot snapshot = _snapshots.get(i);
            Set<ValueRequirement> snapshotSubscriptions = subscriptions.get(i);
            if (snapshotSubscriptions.contains(requirement)) {
                return snapshot.query(requirement);
            }
        }
        return null;
    }

    /**
     * Returns the values from the underlying snapshots if they are available
     * @param requirements the values required, not null
     * @return The values from the underlying snapshots if they are available, values that aren't available will be
     * missing from the results map
     */
    @Override
    public Map<ValueRequirement, ComputedValue> query(Set<ValueRequirement> requirements) {
        ArgumentChecker.notNull(requirements, "requirements");
        Map<ValueRequirement, ComputedValue> results = Maps.newHashMapWithExpectedSize(requirements.size());
        List<Set<ValueRequirement>> subscriptions = _subscriptionSupplier.get();
        for (int i = 0; i < _snapshots.size(); i++) {
            MarketDataSnapshot snapshot = _snapshots.get(i);
            Set<ValueRequirement> snapshotSubscriptions = subscriptions.get(i);
            Set<ValueRequirement> snapshotRequirements = Sets.intersection(snapshotSubscriptions, requirements);
            if (!snapshotRequirements.isEmpty()) {
                Map<ValueRequirement, ComputedValue> snapshotValues = snapshot.query(snapshotRequirements);
                results.putAll(snapshotValues);
            }
        }
        return results;
    }
}