001package net.filebot.format; 002 003import java.math.BigDecimal; 004import java.math.RoundingMode; 005import java.text.DecimalFormat; 006import java.text.DecimalFormatSymbols; 007import java.text.NumberFormat; 008import java.util.Locale; 009import java.util.Map; 010import java.util.Map.Entry; 011 012import net.filebot.util.AlphanumComparator; 013 014public abstract class AutoUnitDecimal implements StringBinding, Comparable<Object> { 015 016 protected final double value; 017 018 public AutoUnitDecimal(double value) { 019 this.value = value; 020 } 021 022 public double getValue() { 023 return value; 024 } 025 026 public long toLong() { 027 return (long) value; 028 } 029 030 public double toDouble() { 031 return value; 032 } 033 034 public int toInteger() { 035 return (int) value; 036 } 037 038 public float toFloat() { 039 return (float) value; 040 } 041 042 public BigDecimal toNumber() { 043 return BigDecimal.valueOf(value); 044 } 045 046 @Override 047 public int compareTo(Object other) { 048 if (other instanceof Number) { 049 Number n = (Number) other; 050 return Double.compare(value, n.doubleValue()); 051 } 052 053 if (other instanceof AutoUnitDecimal) { 054 AutoUnitDecimal n = (AutoUnitDecimal) other; 055 return Double.compare(value, n.value); 056 } 057 058 return AlphanumComparator.getInstance().compare(toString(), other.toString()); 059 } 060 061 @Override 062 public boolean equals(Object other) { 063 return (other instanceof Number && compareTo(other) == 0) || (other instanceof CharSequence && toString().equals(other)); 064 } 065 066 public Object asType(Class<?> c) { 067 if (c == int.class || c == Integer.class) { 068 return toInteger(); 069 } 070 071 if (c == long.class || c == Long.class) { 072 return toLong(); 073 } 074 075 if (c == float.class || c == Float.class) { 076 return toFloat(); 077 } 078 079 if (c == double.class || c == Double.class) { 080 return toDouble(); 081 } 082 083 if (c == Number.class) { 084 return toNumber(); 085 } 086 087 if (c == String.class) { 088 return toString(); 089 } 090 091 // fail with type cast exception message 092 return c.cast(this); 093 } 094 095 public Number div(Number divisor) { 096 return BigDecimal.valueOf(value / divisor.doubleValue()); 097 } 098 099 public Number round(int precision) { 100 return BigDecimal.valueOf(value).setScale(precision, RoundingMode.HALF_UP); 101 } 102 103 public String format(String pattern) { 104 return format(pattern, Locale.ROOT); 105 } 106 107 public String format(String pattern, String locale) { 108 return format(pattern, Locale.forLanguageTag(locale)); 109 } 110 111 public String format(String pattern, Locale locale) { 112 DecimalFormat f = new DecimalFormat(pattern, new DecimalFormatSymbols(locale)); 113 return f.format(value); 114 } 115 116 public String format(Map<Object, String> replacement) { 117 // the first two parameters are required, the rest of the parameter sequence is optional 118 for (Entry<Object, String> m : replacement.entrySet()) { 119 // check Number match or String match 120 if (equals(m.getKey())) { 121 return m.getValue(); 122 } 123 } 124 return toString(); 125 } 126 127 public boolean isFraction() { 128 return value % 1 != 0; 129 } 130 131 public int getFractionDigits() { 132 return isFraction() ? 3 : 0; 133 } 134 135 public String getNumber() { 136 NumberFormat format = NumberFormat.getNumberInstance(Locale.ROOT); 137 format.setGroupingUsed(true); 138 int fractionDigits = getFractionDigits(); 139 format.setMinimumFractionDigits(fractionDigits); 140 format.setMaximumFractionDigits(fractionDigits); 141 return format.format(value); 142 } 143 144 public abstract String getUnit(); 145 146 @Override 147 public String toString() { 148 return getNumber() + getUnit(); 149 } 150 151}