class CurrencyMatrixSpotSourcingFunction extends AbstractCurrencyMatrixSourcingFunction {

  private boolean getRequirements(final CurrencyMatrix matrix, final Set<ValueRequirement> requirements, final Set<Pair<Currency, Currency>> visited, final Pair<Currency, Currency> currencies) {
    if (!visited.add(currencies)) {
      // Gone round in a loop if we've already seen this pair
      throw new IllegalStateException();
    }
    final CurrencyMatrixValue value = matrix.getConversion(currencies.getFirst(), currencies.getSecond());
    if (value != null) {
      return value.accept(new CurrencyMatrixValueVisitor<Boolean>() {

        @Override
        public Boolean visitCross(final CurrencyMatrixCross cross) {
          return getRequirements(matrix, requirements, visited, Pairs.of(currencies.getFirst(), cross.getCrossCurrency()))
              && getRequirements(matrix, requirements, visited, Pairs.of(cross.getCrossCurrency(), currencies.getSecond()));
        }

        @Override
        public Boolean visitFixed(final CurrencyMatrixFixed fixedValue) {
          // Literal value - nothing required
          return Boolean.TRUE;
        }

        @Override
        public Boolean visitValueRequirement(final CurrencyMatrixValueRequirement valueRequirement) {
          requirements.add(tagInput(valueRequirement.getValueRequirement(), currencies.getFirst(), currencies.getSecond()));
          return Boolean.TRUE;
        }

      });
    } else {
      return false;
    }
  }

  public  CurrencyMatrixSpotSourcingFunction();

}