class CurrencyMatrixLookupFunction extends AbstractFunction.NonCompiledInvoker {

  @Override
  public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) {
    final CurrencyPair currencies = (CurrencyPair) target.getValue();
    final ValueProperties.Builder constraints = ValueProperties
        .with(AbstractCurrencyMatrixSourcingFunction.SOURCE_CURRENCY_PROPERTY, currencies.getCounter().getCode())
        .with(AbstractCurrencyMatrixSourcingFunction.TARGET_CURRENCY_PROPERTY, currencies.getBase().getCode());
    ExternalIdBundle matrixIdentifiers = null;
    if (desiredValue.getConstraints().getProperties() != null) {
      for (String constraintName : desiredValue.getConstraints().getProperties()) {
        if (ValuePropertyNames.FUNCTION.equals(constraintName) || constraintName.startsWith(ValuePropertyNames.OUTPUT_RESERVED_PREFIX)) {
          continue;
        }
        final Set<String> values = desiredValue.getConstraints().getValues(constraintName);
        if (CURRENCY_MATRIX_NAME_PROPERTY.equals(constraintName)) {
          if (values.isEmpty()) {
            matrixIdentifiers = ExternalId.of(CurrencyMatrixResolver.IDENTIFIER_SCHEME, getDefaultCurrencyMatrixName()).toBundle();
          } else {
            if (values.size() == 1) {
              matrixIdentifiers = ExternalId.of(CurrencyMatrixResolver.IDENTIFIER_SCHEME, values.iterator().next()).toBundle();
            } else {
              final Collection<ExternalId> identifiers = new ArrayList<ExternalId>(values.size());
              for (String matrixName : values) {
                identifiers.add(ExternalId.of(CurrencyMatrixResolver.IDENTIFIER_SCHEME, matrixName));
              }
              matrixIdentifiers = ExternalIdBundle.of(identifiers);
            }
          }
        } else {
          if (values.isEmpty()) {
            constraints.withAny(constraintName);
          } else {
            constraints.with(constraintName, values);
          }
          if (desiredValue.getConstraints().isOptional(constraintName)) {
            constraints.withOptional(constraintName);
          }
        }
      }
    }
    if (matrixIdentifiers == null) {
      matrixIdentifiers = ExternalId.of(CurrencyMatrixResolver.IDENTIFIER_SCHEME, getDefaultCurrencyMatrixName()).toBundle();
    }
    return Collections.singleton(new ValueRequirement(desiredValue.getValueName(), new ComputationTargetRequirement(CurrencyMatrixResolver.TYPE, matrixIdentifiers), constraints.get()));
  }

  public  CurrencyMatrixLookupFunction(final String defaultCurrencyMatrixName);
  public  CurrencyMatrixLookupFunction(final String[] params);

}