package jnpf.elnFormula; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; public final class FormulaValue { private static final FormulaValue NULL = new FormulaValue(FormulaType.NULL, null, null); private final FormulaType type; private final Object value; private final String missingSlotCode; private FormulaValue(FormulaType type, Object value) { this(type, value, null); } private FormulaValue(FormulaType type, Object value, String missingSlotCode) { this.type = type; this.value = value; this.missingSlotCode = missingSlotCode; } public static FormulaValue decimal(String value) { if (value == null) { throw new IllegalArgumentException("decimal value must not be null"); } return decimal(new BigDecimal(value)); } public static FormulaValue decimal(BigDecimal value) { if (value == null) { throw new IllegalArgumentException("decimal value must not be null"); } return new FormulaValue(FormulaType.DECIMAL, value); } public static FormulaValue decimalList(List values) { if (values == null) { throw new IllegalArgumentException("decimal list must not be null"); } List copy = new ArrayList<>(values.size()); for (FormulaValue value : values) { if (value == null || value.type != FormulaType.DECIMAL) { throw new IllegalArgumentException("decimal list accepts DECIMAL values only"); } copy.add(value); } return new FormulaValue(FormulaType.DECIMAL_LIST, Collections.unmodifiableList(copy)); } public static FormulaValue decimalList(FormulaValue... values) { if (values == null) { throw new IllegalArgumentException("decimal list must not be null"); } List items = new ArrayList<>(values.length); Collections.addAll(items, values); return decimalList(items); } public static FormulaValue text(String value) { if (value == null) { throw new IllegalArgumentException("text value must not be null"); } return new FormulaValue(FormulaType.TEXT, value); } public static FormulaValue bool(boolean value) { return new FormulaValue(FormulaType.BOOLEAN, value); } public static FormulaValue nullValue() { return NULL; } public static FormulaValue nullValue(String missingSlotCode) { if (missingSlotCode == null || missingSlotCode.isEmpty()) { throw new IllegalArgumentException("missing slot code must not be empty"); } return new FormulaValue(FormulaType.NULL, null, missingSlotCode); } public FormulaType getType() { return type; } public String getMissingSlotCode() { return missingSlotCode; } public BigDecimal getDecimal() { require(FormulaType.DECIMAL); return (BigDecimal) value; } @SuppressWarnings("unchecked") public List getDecimalList() { require(FormulaType.DECIMAL_LIST); return (List) value; } public String getText() { require(FormulaType.TEXT); return (String) value; } public boolean getBoolean() { require(FormulaType.BOOLEAN); return (Boolean) value; } public boolean isNull() { return type == FormulaType.NULL; } public String toPlainString() { if (type == FormulaType.NULL) { return "null"; } if (type == FormulaType.TEXT) { return getText(); } if (type == FormulaType.BOOLEAN) { return Boolean.toString(getBoolean()); } if (type == FormulaType.DECIMAL) { BigDecimal decimal = getDecimal(); return decimal.signum() == 0 ? "0" : decimal.stripTrailingZeros().toPlainString(); } StringBuilder result = new StringBuilder("["); List items = getDecimalList(); for (int i = 0; i < items.size(); i++) { if (i > 0) { result.append(','); } result.append(items.get(i).toPlainString()); } return result.append(']').toString(); } private void require(FormulaType expected) { if (type != expected) { throw new IllegalStateException("expected " + expected + " but was " + type); } } @Override public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof FormulaValue)) { return false; } FormulaValue that = (FormulaValue) other; if (type != that.type) { return false; } if (type == FormulaType.DECIMAL) { return getDecimal().compareTo(that.getDecimal()) == 0; } return Objects.equals(value, that.value); } @Override public int hashCode() { Object hashValue = type == FormulaType.DECIMAL ? getDecimal().stripTrailingZeros() : value; return Objects.hash(type, hashValue); } @Override public String toString() { return toPlainString(); } }