Package com.opengamma.web.server

Source Code of com.opengamma.web.server.AggregatedViewDefinitionManager$PortfolioReference

/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.web.server;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang.StringUtils;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.core.config.ConfigSource;
import com.opengamma.core.config.impl.ConfigItem;
import com.opengamma.core.position.Portfolio;
import com.opengamma.core.position.PositionSource;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.engine.view.ViewDefinition;
import com.opengamma.engine.view.compilation.PortfolioCompiler;
import com.opengamma.financial.aggregation.AggregationFunction;
import com.opengamma.financial.aggregation.PortfolioAggregator;
import com.opengamma.financial.portfolio.save.SavePortfolio;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.master.config.ConfigDocument;
import com.opengamma.master.config.ConfigMaster;
import com.opengamma.master.portfolio.PortfolioMaster;
import com.opengamma.master.position.PositionMaster;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.tuple.Pair;

/**
* Manages the lifecycle of aggregated view definitions. There is really no such thing as an aggregated view
* definition, only an aggregated portfolio, but the web client exposes the idea of aggregating a view definition as a
* shortcut for aggregating the underlying portfolio and requesting the same outputs.
*/
public class AggregatedViewDefinitionManager {

  private final PositionSource _positionSource;
  private final SecuritySource _securitySource;
  private final ConfigSource _combinedConfigSource;
  private final ConfigMaster _userConfigMaster;
  private final PortfolioMaster _userPortfolioMaster;
  private final Map<String, AggregationFunction<?>> _portfolioAggregators;
  private final SavePortfolio _portfolioSaver;
 
  private final ReentrantLock _lock = new ReentrantLock();
  private final Map<Pair<UniqueId, List<String>>, PortfolioReference> _aggregatedPortfolios = Maps.newHashMap();
  private final Map<Pair<UniqueId, List<String>>, ViewDefinitionReference> _aggregatedViewDefinitions = Maps.newHashMap();

  public AggregatedViewDefinitionManager(PositionSource positionSource,
                                         SecuritySource securitySource,
                                         ConfigSource combinedConfigSource,
                                         ConfigMaster userConfigMaster,
                                         PortfolioMaster userPortfolioMaster,
                                         PositionMaster userPositionMaster,
                                         Map<String, AggregationFunction<?>> portfolioAggregators) {
    _positionSource = positionSource;
    _securitySource = securitySource;
    _combinedConfigSource = combinedConfigSource;
    _userConfigMaster = userConfigMaster;
    _userPortfolioMaster = userPortfolioMaster;
    _portfolioAggregators = portfolioAggregators;
    _portfolioSaver = new SavePortfolio(Executors.newSingleThreadExecutor(), userPortfolioMaster, userPositionMaster);
  }
 
  public Set<String> getAggregatorNames() {
    return ImmutableSet.copyOf(_portfolioAggregators.keySet());
  }
 
  public UniqueId getViewDefinitionId(UniqueId baseViewDefinitionId, String aggregatorName) {
    List<String> aggregators;
    if (aggregatorName != null) {
      aggregators = Collections.singletonList(aggregatorName);
    } else {
      aggregators = Collections.emptyList();
    }
    return getViewDefinitionId(baseViewDefinitionId, aggregators);
  }

  public UniqueId getViewDefinitionId(UniqueId baseViewDefinitionId, List<String> aggregatorNames) {
    // TODO: what about changes to the base view definition?
    ArgumentChecker.notNull(baseViewDefinitionId, "baseViewDefinitionId");
    ArgumentChecker.notNull(aggregatorNames, "aggregatorNames");
    ViewDefinition baseViewDefinition = (ViewDefinition) _combinedConfigSource.get(baseViewDefinitionId).getValue();
    if (baseViewDefinition == null) {
      throw new OpenGammaRuntimeException("Unknown view definition with unique ID " + baseViewDefinitionId);
    }
    UniqueId basePortfolioId = baseViewDefinition.getPortfolioId();
    if (aggregatorNames.isEmpty() || basePortfolioId == null) {
      return baseViewDefinitionId;
    }
    Pair<UniqueId, List<String>> aggregatedViewDefinitionKey = Pair.of(baseViewDefinition.getUniqueId(), aggregatorNames);
    Pair<UniqueId, List<String>> aggregatedPortfolioKey = Pair.of(basePortfolioId, aggregatorNames);
    _lock.lock();
    try {
      ViewDefinitionReference aggregatedViewDefinitionReference = _aggregatedViewDefinitions.get(aggregatedViewDefinitionKey);
      if (aggregatedViewDefinitionReference == null) {
        PortfolioReference aggregatedPortfolioReference = _aggregatedPortfolios.get(aggregatedPortfolioKey);
        if (aggregatedPortfolioReference == null) {
          UniqueId aggregatedPortfolioId = aggregatePortfolio(basePortfolioId, aggregatorNames);
          aggregatedPortfolioReference = new PortfolioReference(basePortfolioId, aggregatedPortfolioId);
          _aggregatedPortfolios.put(aggregatedPortfolioKey, aggregatedPortfolioReference);
        }
        String aggregatedViewDefinitionName = getAggregatedViewDefinitionName(baseViewDefinition.getName(), aggregatorNames);
        ViewDefinition aggregatedViewDefinition = baseViewDefinition.copyWith(aggregatedViewDefinitionName,
                                                                              aggregatedPortfolioReference.incrementReferenceCount(),
                                                                              baseViewDefinition.getMarketDataUser());
       
        // Treat as a transient view definition that should not be persistent
        //aggregatedViewDefinition.setPersistent(false);
       
        ConfigItem<ViewDefinition> configItem = ConfigItem.of(aggregatedViewDefinition);
        configItem.setName(aggregatedViewDefinition.getName());
        UniqueId viewDefinitionId = _userConfigMaster.add(new ConfigDocument(configItem)).getUniqueId();
        aggregatedViewDefinitionReference = new ViewDefinitionReference(viewDefinitionId, aggregatedPortfolioReference);
        _aggregatedViewDefinitions.put(aggregatedViewDefinitionKey, aggregatedViewDefinitionReference);
      }
      return aggregatedViewDefinitionReference.incrementReferenceCount();
    } finally {
      _lock.unlock();
    }
  }
 
  public void releaseViewDefinition(UniqueId baseViewDefinitionId, String aggregatorName) {
    List<String> aggregatorNames;
    if (aggregatorName != null) {
      aggregatorNames = Collections.singletonList(aggregatorName);
    } else {
      aggregatorNames = Collections.emptyList();
    }
    releaseViewDefinition(baseViewDefinitionId, aggregatorNames);
  }

  public void releaseViewDefinition(UniqueId baseViewDefinitionId, List<String> aggregatorNames) {
    Pair<UniqueId, List<String>> aggregatedViewDefinitionKey = Pair.of(baseViewDefinitionId, aggregatorNames);
    ViewDefinitionReference viewDefinitionReference = _aggregatedViewDefinitions.get(aggregatedViewDefinitionKey);
    if (viewDefinitionReference == null) {
      return;
    }
    _lock.lock();
    try {
      if (viewDefinitionReference.decrementReferenceCount() <= 0) {
        PortfolioReference portfolioReference = viewDefinitionReference.getPortfolioReference();
        if (portfolioReference.decrementReferenceCount() <= 0) {
          _userPortfolioMaster.remove(portfolioReference.getPortfolioId());
          Pair<UniqueId, List<String>> aggregatedPortfolioKey = Pair.of(portfolioReference.getBasePortfolioId(), aggregatorNames);
          _aggregatedPortfolios.remove(aggregatedPortfolioKey);
        }
        _userConfigMaster.remove(viewDefinitionReference.getViewDefinitionId());
        _aggregatedViewDefinitions.remove(aggregatedViewDefinitionKey);
      }
    } finally {
      _lock.unlock();
    }
  }
 
  private String getAggregatedViewDefinitionName(String baseViewDefinitionName, List<String> aggregatorNames) {
    return baseViewDefinitionName + " aggregated by " + StringUtils.join(aggregatorNames, ", ");
  }

  private UniqueId aggregatePortfolio(UniqueId basePortfolioId, List<String> aggregatorNames) {
    // REVIEW jonathan 2011-11-13 -- portfolio aggregation is currently painful. The positions obtained from the
    // position source during the orginal portfolio lookup contain munged identifiers that do not correspond to
    // anything in the position master. We end up rewriting the positions even though there is no need, then we cannot
    // clean them up when the portfolio is no longer required in case other portfolios have now referenced the new
    // positions.
    Portfolio basePortfolio = _positionSource.getPortfolio(basePortfolioId, VersionCorrection.LATEST);
    Portfolio resolvedPortfolio =
        PortfolioCompiler.resolvePortfolio(basePortfolio, Executors.newSingleThreadExecutor(), _securitySource);
    List<AggregationFunction<?>> aggregationFunctions = Lists.newArrayListWithCapacity(aggregatorNames.size());
    for (String aggregatorName : aggregatorNames) {
      AggregationFunction<?> aggregationFunction = _portfolioAggregators.get(aggregatorName);
      if (aggregationFunction == null) {
        throw new OpenGammaRuntimeException("Unknown aggregator '" + aggregatorName + "'");
      }
      aggregationFunctions.add(aggregationFunction);
    }
    PortfolioAggregator aggregator = new PortfolioAggregator(aggregationFunctions);
    Portfolio aggregatedPortfolio = aggregator.aggregate(resolvedPortfolio);
    return _portfolioSaver.savePortfolio(aggregatedPortfolio, false);
  }
 
  //-------------------------------------------------------------------------
  private static class PortfolioReference {
   
    private final UniqueId _basePortfolioId;
    private final UniqueId _portfolioId;
    private long _referenceCount;
   
    public PortfolioReference(UniqueId basePortfolioId, UniqueId portfolioId) {
      _basePortfolioId = basePortfolioId;
      _portfolioId = portfolioId;
    }
   
    public UniqueId getBasePortfolioId() {
      return _basePortfolioId;
    }
   
    public UniqueId getPortfolioId() {
      return _portfolioId;
    }
   
    public UniqueId incrementReferenceCount() {
      _referenceCount++;
      return _portfolioId;
    }
   
    public long decrementReferenceCount() {
      return --_referenceCount;
    }
   
  }
 
  private static class ViewDefinitionReference {
   
    private final UniqueId _viewDefinitionId;
    private final PortfolioReference _portfolioReference;
    private long _referenceCount;
   
    public ViewDefinitionReference(UniqueId viewDefinitionId, PortfolioReference portfolioReference) {
      _viewDefinitionId = viewDefinitionId;
      _portfolioReference = portfolioReference;
    }

    public UniqueId getViewDefinitionId() {
      return _viewDefinitionId;
    }
   
    public PortfolioReference getPortfolioReference() {
      return _portfolioReference;
    }
   
    public UniqueId incrementReferenceCount() {
      _referenceCount++;
      return _viewDefinitionId;
    }
   
    public long decrementReferenceCount() {
      return --_referenceCount;
    }
   
  }

}
TOP

Related Classes of com.opengamma.web.server.AggregatedViewDefinitionManager$PortfolioReference

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.