Package com.opengamma.engine.view.worker

Source Code of com.opengamma.engine.view.worker.ViewExecutionDataProvider$CompositePermissionProvider

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

import java.util.Collections;
import java.util.List;
import java.util.Set;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.opengamma.engine.marketdata.MarketDataPermissionProvider;
import com.opengamma.engine.marketdata.MarketDataProvider;
import com.opengamma.engine.marketdata.resolver.MarketDataProviderResolver;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.livedata.UserPrincipal;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.tuple.Pair;

/**
* A source of market data that aggregates data from multiple underlying {@link MarketDataProvider}s.
*/
public class ViewExecutionDataProvider {

  /** The market data user */
  private final UserPrincipal _user;
  /** The underlying providers in priority order. */
  private final List<MarketDataProvider> _providers;
  /** The market data specifications in priority order. */
  private final List<MarketDataSpecification> _specs;
  private final MarketDataPermissionProvider _permissionsProvider;

  /**
   * @param user The user requesting the data, not null
   * @param specs Specifications of the underlying providers in priority order, not empty
   * @param resolver For resolving market data specifications into providers, not null
   * @throws IllegalArgumentException If any of the data providers in {@code specs} can't be resolved
   */
  public ViewExecutionDataProvider(final UserPrincipal user,
      final List<MarketDataSpecification> specs,
      final MarketDataProviderResolver resolver) {
    ArgumentChecker.notNull(user, "user");
    ArgumentChecker.notEmpty(specs, "specs");
    ArgumentChecker.notNull(resolver, "resolver");
    _user = user;
    _specs = ImmutableList.copyOf(specs);
    if (_specs.size() == 1) {
      final MarketDataProvider provider = resolver.resolve(user, _specs.get(0));
      if (provider == null) {
        throw new IllegalArgumentException("Unable to resolve market data spec " + _specs.get(0));
      }
      _providers = Collections.singletonList(provider);
      _permissionsProvider = provider.getPermissionProvider();
    } else {
      _providers = Lists.newArrayListWithCapacity(_specs.size());
      for (final MarketDataSpecification spec : _specs) {
        final MarketDataProvider provider = resolver.resolve(user, spec);
        if (provider == null) {
          throw new IllegalArgumentException("Unable to resolve market data spec " + spec);
        }
        _providers.add(provider);
      }
      _permissionsProvider = new CompositePermissionProvider();
    }
  }

  public UserPrincipal getMarketDataUser() {
    return _user;
  }

  protected List<MarketDataProvider> getProviders() {
    return _providers;
  }

  public List<MarketDataSpecification> getSpecifications() {
    return _specs;
  }

  /**
   * @return An permissions provider backed by the permissions providers of the underlying market data providers
   */
  public MarketDataPermissionProvider getPermissionProvider() {
    return _permissionsProvider;
  }

  /**
   * Divides up the specifications into a set for each underlying provider. The values from each underlying will have been tagged with a provider property which indicates the underlying they came
   * from. This is removed from the returned result so the original value specifications as used by the underlying are returned.
   *
   * @param numProviders the number of providers in total
   * @param specifications The market data specifications
   * @return A set of specifications for each underlying provider, in the same order as the providers
   */
  protected static List<Set<ValueSpecification>> partitionSpecificationsByProvider(final int numProviders, final Set<ValueSpecification> specifications) {
    if (numProviders == 1) {
      return Collections.singletonList(specifications);
    } else {
      final List<Set<ValueSpecification>> result = Lists.newArrayListWithCapacity(numProviders);
      for (int i = 0; i < numProviders; i++) {
        result.add(Sets.<ValueSpecification>newHashSet());
      }
      for (final ValueSpecification specification : specifications) {
        String provider = specification.getProperty(ValuePropertyNames.DATA_PROVIDER);
        if (provider != null) {
          final ValueProperties.Builder underlyingProperties = specification.getProperties().copy().withoutAny(ValuePropertyNames.DATA_PROVIDER);
          final int slash = provider.indexOf('/');
          if (slash > 0) {
            underlyingProperties.with(ValuePropertyNames.DATA_PROVIDER, provider.substring(0, slash));
            provider = provider.substring(slash + 1);
          }
          try {
            result.get(Integer.parseInt(provider)).add(new ValueSpecification(specification.getValueName(), specification.getTargetSpecification(), underlyingProperties.get()));
          } catch (final NumberFormatException e) {
            // Ignore
          }
        }
      }
      return result;
    }
  }

  /**
   * Identifies the provider a given specification is used for. The values from the underlying will have been tagged with a provider property which indicates the underlying. Thsi is removed from the
   * result so the original value specification as used by the underlying is returned.
   *
   * @param specification the specification to test
   * @return the provider index and the underlying's specification, or null if it could not be found
   */
  protected static Pair<Integer, ValueSpecification> getProviderSpecification(final ValueSpecification specification) {
    String provider = specification.getProperty(ValuePropertyNames.DATA_PROVIDER);
    if (provider != null) {
      final ValueProperties.Builder underlyingProperties = specification.getProperties().copy().withoutAny(ValuePropertyNames.DATA_PROVIDER);
      final int slash = provider.indexOf('/');
      if (slash > 0) {
        underlyingProperties.with(ValuePropertyNames.DATA_PROVIDER, provider.substring(0, slash));
        provider = provider.substring(slash + 1);
      }
      try {
        return Pair.of(Integer.parseInt(provider), new ValueSpecification(specification.getValueName(), specification.getTargetSpecification(), underlyingProperties.get()));
      } catch (final NumberFormatException e) {
        // Ignore
      }
    }
    return null;
  }

  /**
   * Converts a value specification as used by a given underlying to one that can be used by this provider. An integer identifier for the underlying provider will be put into a property that the
   * {@link #partitionSpecificationsByProvider} helper will use to map the specification back to the originating underlying.
   *
   * @param providerId the index of the provider in the list
   * @param underlying the value specification as used by the underlying
   * @return a value specification for external use
   */
  protected static ValueSpecification convertUnderlyingSpecification(final int providerId, final ValueSpecification underlying) {
    final ValueProperties.Builder properties = underlying.getProperties().copy();
    final String dataProvider = underlying.getProperty(ValuePropertyNames.DATA_PROVIDER);
    if (dataProvider != null) {
      properties.withoutAny(ValuePropertyNames.DATA_PROVIDER).with(ValuePropertyNames.DATA_PROVIDER, dataProvider + "/" + Integer.toString(providerId));
    } else {
      properties.with(ValuePropertyNames.DATA_PROVIDER, Integer.toString(providerId));
    }
    return new ValueSpecification(underlying.getValueName(), underlying.getTargetSpecification(), properties.get());
  }

  /**
   * {@link MarketDataPermissionProvider} that checks the permissions using the underlying {@link MarketDataProvider}s. The underlying provider will be the one that returned the original availability
   * of the data.
   */
  private class CompositePermissionProvider implements MarketDataPermissionProvider {

    /**
     * Checks permissions with the underlying providers and returns any requirements for which the user has no permissions with any provider.
     *
     * @param user The user whose market data permissions should be checked
     * @param specifications The market data to check access to
     * @return Values for which the user has no permissions with any of the underlying providers
     */
    @Override
    public Set<ValueSpecification> checkMarketDataPermissions(final UserPrincipal user, final Set<ValueSpecification> specifications) {
      final List<Set<ValueSpecification>> specsByProvider = partitionSpecificationsByProvider(_providers.size(), specifications);
      final Set<ValueSpecification> missingSpecifications = Sets.newHashSet();
      for (int i = 0; i < _providers.size(); i++) {
        final MarketDataPermissionProvider permissionProvider = _providers.get(i).getPermissionProvider();
        final Set<ValueSpecification> specsForProvider = specsByProvider.get(i);
        final Set<ValueSpecification> missing = permissionProvider.checkMarketDataPermissions(user, specsForProvider);
        if (!missing.isEmpty()) {
          for (final ValueSpecification specification : missing) {
            missingSpecifications.add(convertUnderlyingSpecification(i, specification));
          }
        }
      }
      return missingSpecifications;
    }
  }

}
TOP

Related Classes of com.opengamma.engine.view.worker.ViewExecutionDataProvider$CompositePermissionProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.