/**
  * Test if all providers returns valid meta data.
  *
  * @see javax.money.convert.ProviderContext
  */
 @Test(
     description =
         "4.3.1 Test if all CurrencyConversion instances returns valid ConversionContext, accessed by "
             + "ConversionQuery/CurrencyUnit.")
 @SpecAssertion(id = "431-A3", section = "4.3.1")
 public void testProviderMetadata3WithContext() {
   for (String providerName : MonetaryConversions.getConversionProviderNames()) {
     ConversionQuery query =
         ConversionQueryBuilder.of()
             .setTermCurrency(Monetary.getCurrency("XXX"))
             .setProviderName(providerName)
             .build();
     if (MonetaryConversions.isConversionAvailable(query)) {
       CurrencyConversion conv = MonetaryConversions.getConversion(query);
       ConversionContext ctx = conv.getContext();
       AssertJUnit.assertNotNull(
           "ExchangeProvider must return a valid ProviderContext, but returned null: "
               + providerName,
           ctx);
       AssertJUnit.assertEquals(
           "ExchangeProvider's ProviderContext returns invalid name: " + providerName,
           providerName,
           ctx.getProviderName());
       AssertJUnit.assertNotNull(
           "ExchangeProvider's ProviderContext declares invalid RateTypes to be returned (null): "
               + providerName,
           ctx.getRateType());
     }
   }
 }
 /**
  * Test if all providers returns valid meta data.
  *
  * @see javax.money.convert.ProviderContext
  */
 @Test(
     description =
         "4.3.1 Test if all CurrencyConversion instances returns valid ConversionContext, accessed by "
             + "currency code.")
 @SpecAssertion(id = "431-A3", section = "4.3.1")
 public void testProviderMetadata2() {
   for (String providerName : MonetaryConversions.getConversionProviderNames()) {
     if (MonetaryConversions.isConversionAvailable("XXX", providerName)) {
       CurrencyConversion conv = MonetaryConversions.getConversion("XXX", providerName);
       ConversionContext ctx = conv.getContext();
       AssertJUnit.assertNotNull(
           "ExchangeProvider must return a valid ProviderContext, but returned null: "
               + providerName,
           ctx);
       AssertJUnit.assertEquals(
           "ExchangeProvider's ProviderContext returns invalid name: " + providerName,
           providerName,
           ctx.getProviderName());
       AssertJUnit.assertNotNull(
           "ExchangeProvider's ProviderContext declares invalid RateTypes to be returned (null): "
               + providerName,
           ctx.getRateType());
     }
   }
 }
  /**
   * comparator to sort the {@link MonetaryAmount} considering the {@link ExchangeRate}
   *
   * @param provider the rate provider to be used, not null.
   * @return the sort of {@link MonetaryAmount} using {@link ExchangeRate}
   */
  public static Comparator<? super MonetaryAmount> sortValuable(ExchangeRateProvider provider) {

    return (m1, m2) -> {
      CurrencyConversion conversion = provider.getCurrencyConversion(m1.getCurrency());
      return m1.compareTo(conversion.apply(m2));
    };
  }
  /**
   * return the maximum value, if the monetary amounts have different currencies, will converter
   * first using the given ExchangeRateProvider
   *
   * @param provider the ExchangeRateProvider to convert the currencies
   * @return the maximum value
   */
  public static BinaryOperator<MonetaryAmount> max(ExchangeRateProvider provider) {

    return (m1, m2) -> {
      CurrencyConversion conversion = provider.getCurrencyConversion(m1.getCurrency());

      if (m1.isGreaterThan(conversion.apply(m2))) {
        return m1;
      }
      return m2;
    };
  }
  /**
   * return the sum and convert all values to specific currency using the provider, if necessary
   *
   * @param provider the rate provider to be used, not null.
   * @param currency currency
   * @return the list convert to specific currency unit
   */
  public static BinaryOperator<MonetaryAmount> sum(
      ExchangeRateProvider provider, CurrencyUnit currency) {
    CurrencyConversion currencyConversion = provider.getCurrencyConversion(currency);

    return (m1, m2) -> currencyConversion.apply(m1).add(currencyConversion.apply(m2));
  }