Overview
The Parameters class encapsulates input values required for price calculations. It provides type-safe access to various parameter types including numeric values, money amounts, dates, and times.
Class Definition
public class Parameters {
private final Map<String, Object> values;
public Parameters();
public Parameters(Map<String, Object> values);
}
Factory Methods
empty()
public static Parameters empty()
Creates an empty parameter set.
Returns:
- Empty Parameters instance
Example:
Parameters params = Parameters.empty();
// Use with calculators that require no parameters
Money price = fixedCalculator.calculate(params);
of() - Single Parameter
public static Parameters of(String key, Object value)
Creates a parameter set with a single key-value pair.
Example:
Parameters params = Parameters.of("quantity", BigDecimal.valueOf(10));
Money price = calculator.calculate(params);
of() - Multiple Parameters
Overloaded factory methods for 2-5 parameters:
Parameters.of(String k1, Object v1, String k2, Object v2)
Parameters.of(String k1, Object v1, String k2, Object v2, String k3, Object v3)
Parameters.of(String k1, Object v1, ..., String k4, Object v4)
Parameters.of(String k1, Object v1, ..., String k5, Object v5)
Example:
// Two parameters
Parameters params = Parameters.of(
"base", Money.pln(1000),
"unit", ChronoUnit.MONTHS
);
// Three parameters
Parameters params = Parameters.of(
"quantity", BigDecimal.valueOf(15),
"date", LocalDate.of(2024, 6, 1),
"region", "EU"
);
Type-Safe Getters
getBigDecimal()
public BigDecimal getBigDecimal(String key)
Retrieves a numeric parameter value.
Returns:
Supported Conversions:
BigDecimal → returned as-is
Number (Integer, Long, Double, etc.) → converted to BigDecimal
String → parsed to BigDecimal
Throws:
IllegalArgumentException - If value cannot be converted to BigDecimal
Example:
Parameters params = Parameters.of("quantity", 15);
BigDecimal qty = params.getBigDecimal("quantity");
// Returns: BigDecimal(15)
Parameters params2 = Parameters.of("quantity", "15.5");
BigDecimal qty2 = params2.getBigDecimal("quantity");
// Returns: BigDecimal(15.5)
getMoney()
public Money getMoney(String key)
Retrieves a money parameter value.
Returns:
Money value with amount and currency
Supported Conversions:
Money → returned as-is
String → parsed from format "CURRENCY AMOUNT" (e.g., "PLN 1999.00")
Throws:
IllegalArgumentException - If value cannot be converted to Money
Example:
// Direct Money object
Parameters params = Parameters.of("baseAmount", Money.pln(1000));
Money amount = params.getMoney("baseAmount");
// Returns: Money{value=1000.00, currency=PLN}
// String parsing
Parameters params2 = Parameters.of("baseAmount", "EUR 500.00");
Money amount2 = params2.getMoney("baseAmount");
// Returns: Money{value=500.00, currency=EUR}
getLocalDate()
LocalDate getLocalDate(String key)
Retrieves a date parameter value.
Returns:
Supported Conversions:
LocalDate → returned as-is
String → parsed from ISO-8601 format "YYYY-MM-DD"
Throws:
IllegalArgumentException - If value cannot be converted to LocalDate
Example:
// Direct LocalDate object
Parameters params = Parameters.of("date", LocalDate.of(2024, 6, 1));
LocalDate date = params.getLocalDate("date");
// Returns: 2024-06-01
// String parsing
Parameters params2 = Parameters.of("date", "2024-06-15");
LocalDate date2 = params2.getLocalDate("date");
// Returns: 2024-06-15
getTime()
LocalDateTime getTime(String key)
Retrieves a timestamp parameter value.
Returns:
Supported Conversions:
LocalDateTime → returned as-is
String → parsed from ISO-8601 format "YYYY-MM-DDTHH:MM:SS"
Throws:
IllegalArgumentException - If value cannot be converted to LocalDateTime
Example:
// Direct LocalDateTime object
Parameters params = Parameters.of(
"time",
LocalDateTime.of(2024, 6, 1, 14, 30)
);
LocalDateTime time = params.getTime("time");
// Returns: 2024-06-01T14:30:00
// String parsing
Parameters params2 = Parameters.of("time", "2024-06-01T10:15:30");
LocalDateTime time2 = params2.getTime("time");
// Returns: 2024-06-01T10:15:30
get()
public Object get(String key)
Retrieves a raw parameter value without type conversion.
Returns:
Object - Raw parameter value
Example:
Parameters params = Parameters.of("region", "EU");
String region = (String) params.get("region");
// Returns: "EU"
Timestamp Methods
Special methods for versioned component calculations.
timestamp()
public Optional<LocalDateTime> timestamp()
Retrieves the timestamp parameter used for version lookups.
Returns:
Optional<LocalDateTime> - Timestamp if present, empty otherwise
Example:
Parameters params = Parameters.of(
"timestamp",
LocalDateTime.of(2024, 6, 1, 12, 0)
);
Optional<LocalDateTime> ts = params.timestamp();
if (ts.isPresent()) {
// Use timestamp for version selection
ComponentVersion version = component.versionAt(ts.get());
}
requireTimestamp()
public LocalDateTime requireTimestamp()
Retrieves the timestamp parameter, throwing exception if not present.
Returns:
LocalDateTime - Timestamp value
Throws:
IllegalArgumentException - If timestamp parameter is not present
Example:
Parameters params = Parameters.of(
"timestamp",
LocalDateTime.of(2024, 6, 1, 12, 0)
);
LocalDateTime ts = params.requireTimestamp();
// Returns: 2024-06-01T12:00:00
// Without timestamp - throws exception
Parameters params2 = Parameters.empty();
LocalDateTime ts2 = params2.requireTimestamp();
// Throws: IllegalArgumentException - "Parameters must contain 'timestamp'..."
Validation Methods
contains()
public boolean contains(String key)
Checks if a parameter exists.
Returns:
true if parameter exists, false otherwise
Example:
Parameters params = Parameters.of("quantity", BigDecimal.valueOf(10));
boolean hasQuantity = params.contains("quantity");
// Returns: true
boolean hasDate = params.contains("date");
// Returns: false
containsAll()
public boolean containsAll(Set<String> keys)
Checks if all specified parameters exist.
Set of parameter names to check
Returns:
true if all parameters exist, false otherwise
Example:
Parameters params = Parameters.of(
"base", Money.pln(1000),
"unit", ChronoUnit.MONTHS
);
// Check required parameters
Set<String> required = Set.of("base", "unit");
boolean hasAll = params.containsAll(required);
// Returns: true
Set<String> missing = Set.of("base", "unit", "date");
boolean hasAll2 = params.containsAll(missing);
// Returns: false ("date" is missing)
Utility Methods
keys()
public Set<String> keys()
Returns all parameter names.
Returns:
Set<String> - Set of parameter names
Example:
Parameters params = Parameters.of(
"quantity", BigDecimal.valueOf(10),
"date", LocalDate.of(2024, 6, 1)
);
Set<String> keys = params.keys();
// Returns: ["quantity", "date"]
getValues()
public Map<String, Object> getValues()
Returns the internal parameter map.
Returns:
Map<String, Object> - All parameters
Example:
Parameters params = Parameters.of("quantity", BigDecimal.valueOf(10));
Map<String, Object> values = params.getValues();
// Returns: {"quantity": BigDecimal(10)}
with()
public Parameters with(String key, Object value)
Creates a new Parameters instance with an additional parameter.
Returns:
Parameters - New instance with added parameter
This method does not modify the original Parameters instance (immutable style).
Example:
Parameters original = Parameters.of("quantity", BigDecimal.valueOf(10));
Parameters extended = original.with("date", LocalDate.of(2024, 6, 1));
// Original unchanged
original.contains("date"); // Returns: false
// New instance has both parameters
extended.contains("quantity"); // Returns: true
extended.contains("date"); // Returns: true
Common Usage Patterns
Validating Required Parameters
public Money calculate(Parameters params) {
// Get required fields from calculator type
Set<String> required = getType().requiredCalculationFields();
// Validate all required parameters are present
if (!params.containsAll(required)) {
throw new IllegalArgumentException(
"Missing required parameters: " + required
);
}
// Safe to proceed with calculation
BigDecimal quantity = params.getBigDecimal("quantity");
return calculatePrice(quantity);
}
Building Parameters Incrementally
// Start with base parameters
Parameters params = Parameters.of(
"quantity", BigDecimal.valueOf(10)
);
// Add timestamp for versioned calculation
params = params.with(
"timestamp",
LocalDateTime.now()
);
// Add context-specific parameters
if (isPremiumCustomer) {
params = params.with("customerTier", "PREMIUM");
}
Money price = calculator.calculate(params);
Parameter Conversion
// Accept flexible input formats
Parameters params = Parameters.of(
"quantity", "15", // String
"baseAmount", "PLN 1000", // String with currency
"date", "2024-06-01" // ISO date string
);
// Type-safe extraction with automatic conversion
BigDecimal qty = params.getBigDecimal("quantity");
// Returns: BigDecimal(15)
Money amount = params.getMoney("baseAmount");
// Returns: Money{value=1000, currency=PLN}
LocalDate date = params.getLocalDate("date");
// Returns: 2024-06-01
Scenario Simulation
// Create multiple scenarios for testing
List<Parameters> scenarios = List.of(
Parameters.of("quantity", BigDecimal.valueOf(5)),
Parameters.of("quantity", BigDecimal.valueOf(15)),
Parameters.of("quantity", BigDecimal.valueOf(25)),
Parameters.of("quantity", BigDecimal.valueOf(50))
);
// Simulate calculator across all scenarios
Map<Parameters, Money> results = calculator.simulate(scenarios);
results.forEach((params, price) -> {
System.out.printf("Quantity %s → %s%n",
params.getBigDecimal("quantity"),
price
);
});
// Output:
// Quantity 5 → PLN 100.00
// Quantity 15 → PLN 105.00
// Quantity 25 → PLN 110.00
// Quantity 50 → PLN 120.00
ParameterValue Interface
Advanced: Expressions for computing parameter values from component results.
public sealed interface ParameterValue
permits ValueOf, SumOf, DifferenceOf, ProductOf {
Money evaluate(Map<Component, Money> componentResults);
}
ValueOf
References a single component’s value.
record ValueOf(String componentName) implements ParameterValue
Example:
ParameterValue basePrice = new ValueOf("basePrice");
Money value = basePrice.evaluate(componentResults);
SumOf
Sums multiple component values.
record SumOf(String... componentNames) implements ParameterValue
Example:
// Total = basePrice + shipping + handling
ParameterValue total = new SumOf("basePrice", "shipping", "handling");
Money value = total.evaluate(componentResults);
DifferenceOf
Calculates difference between two components.
record DifferenceOf(String minuendComponent, String subtrahendComponent)
implements ParameterValue
Example:
// Profit = revenue - costs
ParameterValue profit = new DifferenceOf("revenue", "costs");
Money value = profit.evaluate(componentResults);
ProductOf
Multiplies component value by a factor.
record ProductOf(String componentName, BigDecimal factor)
implements ParameterValue
Example:
// Premium = basePrice × 1.5
ParameterValue premium = new ProductOf("basePrice", BigDecimal.valueOf(1.5));
Money value = premium.evaluate(componentResults);
Usage in Component Dependencies
// Component that depends on other components
Component taxCalculation = Component.create(
"VAT",
taxCalculator,
Map.of(
"baseAmount", new SumOf("productPrice", "shipping")
)
);
// When calculated, VAT baseAmount will be:
// productPrice result + shipping result