private static List<RequirementBasedColumnKey> getRequirements(
      ViewDefinition viewDefinition, EnumSet<ComputationTargetType> targetTypes) {
    List<RequirementBasedColumnKey> result = new ArrayList<RequirementBasedColumnKey>();
    for (ViewCalculationConfiguration calcConfig :
        viewDefinition.getAllCalculationConfigurations()) {
      String calcConfigName = calcConfig.getName();
      if (targetTypes.contains(ComputationTargetType.POSITION)
          || targetTypes.contains(ComputationTargetType.PORTFOLIO_NODE)) {
        for (Pair<String, ValueProperties> portfolioOutput :
            calcConfig.getAllPortfolioRequirements()) {
          String valueName = portfolioOutput.getFirst();
          ValueProperties constraints = portfolioOutput.getSecond();
          RequirementBasedColumnKey columnKey =
              new RequirementBasedColumnKey(calcConfigName, valueName, constraints);
          result.add(columnKey);
        }
      }

      for (ValueRequirement specificRequirement : calcConfig.getSpecificRequirements()) {
        if (!targetTypes.contains(specificRequirement.getTargetSpecification().getType())) {
          continue;
        }
        String valueName = specificRequirement.getValueName();
        ValueProperties constraints = specificRequirement.getConstraints();
        RequirementBasedColumnKey columnKey =
            new RequirementBasedColumnKey(calcConfigName, valueName, constraints);
        result.add(columnKey);
      }
    }
    return result;
  }
  /**
   * Adds portfolio targets to the dependency graphs as required, and fully resolves the portfolio
   * structure.
   *
   * @param compilationContext the context of the view definition compilation
   * @param versionCorrection the version-correction at which to operate, not null
   * @param forcePortfolioResolution {@code true} if there are external portfolio targets, false
   *     otherwise
   * @return the fully-resolved portfolio structure if any portfolio targets were required, null
   *     otherwise.
   */
  protected static Portfolio execute(
      ViewCompilationContext compilationContext,
      VersionCorrection versionCorrection,
      boolean forcePortfolioResolution) {
    // Everything we do here is geared towards the avoidance of resolution (of portfolios,
    // positions, securities)
    // wherever possible, to prevent needless dependencies (on a position master, security master)
    // when a view never
    // really has them.

    if (!isPortfolioOutputEnabled(compilationContext.getViewDefinition())) {
      // Doesn't even matter if the portfolio can't be resolved - we're not outputting anything at
      // the portfolio level
      // (which might be because the user knows the portfolio can't be resolved right now) so there
      // are no portfolio
      // targets to add to the dependency graph.
      return null;
    }

    Portfolio portfolio =
        forcePortfolioResolution ? getPortfolio(compilationContext, versionCorrection) : null;

    for (ViewCalculationConfiguration calcConfig :
        compilationContext.getViewDefinition().getAllCalculationConfigurations()) {
      if (calcConfig.getAllPortfolioRequirements().size() == 0) {
        // No portfolio requirements for this calculation configuration - avoid further processing.
        continue;
      }

      // Actually need the portfolio now
      if (portfolio == null) {
        portfolio = getPortfolio(compilationContext, versionCorrection);
      }

      DependencyGraphBuilder builder = compilationContext.getBuilders().get(calcConfig.getName());

      // Cache PortfolioNode, Trade and Position entities
      CachingComputationTargetResolver resolver =
          compilationContext.getServices().getComputationTargetResolver();
      resolver.cachePortfolioNodeHierarchy(portfolio.getRootNode());
      cacheTradesPositionsAndSecurities(resolver, portfolio.getRootNode());

      // Add portfolio requirements to the dependency graph
      PortfolioCompilerTraversalCallback traversalCallback =
          new PortfolioCompilerTraversalCallback(builder, calcConfig);
      PortfolioNodeTraverser.depthFirst(traversalCallback).traverse(portfolio.getRootNode());
    }

    return portfolio;
  }