Class CurrencyReconciler

java.lang.Object
com.eqixiac.equinix.design.value.CurrencyReconciler

public final class CurrencyReconciler extends Object
The single reconciliation rule shared by every design-time cost model (TcoEngine, SavingsCalculatorEngine, MetroOptimizerEngine, DeploymentWizardEngine, and plan value realization).

Rule: monetary amounts may only be added, subtracted, or compared when they share a currency. This SDK models prices with no FX rate at all — live Fabric pricing for an EMEA metro can quote EUR while the bundled cloud-egress reference figures are USD — so summing across currencies would fabricate a figure that is simply wrong. When components disagree, this helper refuses to produce a combined total and instead exposes the per-currency subtotals and a human-readable reason, so the caller can mark the total unpriced/mixed (mirroring the existing priced/complete guards) rather than emit a false number labelled as authoritative.

Used two ways:

The predicates deliberately treat an unknown (null/blank) currency as "not provably different": they block a combination only when two currencies are both known and genuinely differ, so a malformed null currency never silently flips an all-one-currency calculation to unpriced. Absence is tracked separately via sawUnknownCurrency().

Not thread-safe; each computation builds its own instance.

  • Method Details

    • create

      public static CurrencyReconciler create()
      Creates an empty reconciler.
    • add

      public CurrencyReconciler add(Currency currency, BigDecimal monthlyAmount, BigDecimal setupAmount)
      Records a priced component. A null/blank currency contributes no amount (it cannot be reconciled) and is remembered via sawUnknownCurrency(); null amounts count as zero.
      Parameters:
      currency - the component's currency (may be null)
      monthlyAmount - the component's monthly-recurring amount
      setupAmount - the component's one-time setup amount
      Returns:
      this reconciler
    • add

      public CurrencyReconciler add(String currencyCode, BigDecimal monthlyAmount, BigDecimal setupAmount)
      Records a priced component by currency code. See add(Currency, BigDecimal, BigDecimal).
    • addMonthly

      public CurrencyReconciler addMonthly(Currency currency, BigDecimal monthlyAmount)
      Records a monthly-only component (setup treated as zero).
    • isEmpty

      public boolean isEmpty()
      true when no priceable component has been recorded.
    • sawUnknownCurrency

      public boolean sawUnknownCurrency()
      true when at least one component had a null/blank (unreconcilable) currency.
    • currencies

      public Set<String> currencies()
      The distinct currency codes recorded, in first-seen order.
    • distinctCurrencyCount

      public int distinctCurrencyCount()
      How many distinct currencies were recorded.
    • isMixed

      public boolean isMixed()
      true when components span more than one currency, so no single total is valid.
    • isReconciled

      public boolean isReconciled()
      true when all recorded components share a currency (or none were recorded).
    • soleCurrency

      public String soleCurrency()
      The sole currency when exactly one was recorded, otherwise null.
    • soleCurrencyOr

      public String soleCurrencyOr(String fallback)
      The sole currency, or fallback when empty or mixed.
    • monthlyTotal

      public Optional<BigDecimal> monthlyTotal()
      The combined monthly total — present only when the components reconcile to a single currency, empty when they are mixed (a cross-currency sum would be false).

      Empty-reconciler caveat: when nothing priceable was recorded — including when every added component carried a null/blank currency — this returns Optional.of(ZERO), not Optional.empty(): zero is the correct sum of no components, but it is not evidence that anything was priced. Callers must therefore pair this with isEmpty() / sawUnknownCurrency() (as the engines' priced/complete flags do) before presenting the total, or an all-unpriceable accumulation reads as "costs $0" — exactly the fabricated figure this class exists to prevent.

    • setupTotal

      public Optional<BigDecimal> setupTotal()
      The combined setup total, with the same single-currency guard — and the same empty-reconciler caveat — as monthlyTotal().
    • monthlySubtotals

      public Map<String, BigDecimal> monthlySubtotals()
      Monthly subtotal per currency, in first-seen order.
    • setupSubtotals

      public Map<String, BigDecimal> setupSubtotals()
      Setup subtotal per currency, in first-seen order.
    • describeCurrencies

      public String describeCurrencies()
      The currencies joined for a message, e.g. "USD and EUR".
    • describeMonthlySubtotals

      public String describeMonthlySubtotals()
      The per-currency monthly subtotals for a message, e.g. "USD 2000.00, EUR 350.00".
    • knownDifferent

      public static boolean knownDifferent(String a, String b)
      true only when both currencies are known and genuinely differ — the guard for "may I subtract/compare these two?". A null/blank on either side yields false (not provably different), so an absent currency never fabricates a mismatch.
    • knownDifferent

      public static boolean knownDifferent(Currency a, Currency b)
    • sameKnownCurrency

      public static boolean sameKnownCurrency(String a, String b)
      true when both currencies are known and equal.