From 71a75947f39ff6d227252bca4619bad7f23f20c9 Mon Sep 17 00:00:00 2001 From: serso Date: Fri, 15 Apr 2016 00:12:45 +0200 Subject: [PATCH] Unit converter refactor --- .../calculator/converter/Converter.java | 2 +- .../converter/ConverterFragment.java | 211 ++---------------- .../calculator/converter/Convertible.java | 12 + .../converter/ConvertibleDimension.java | 14 ++ .../android/calculator/converter/Named.java | 49 ++++ .../calculator/converter/NamedDimension.java | 38 ---- .../converter/NumeralBaseConvertible.java | 32 +++ .../converter/NumeralBaseDimension.java | 43 ++++ .../calculator/converter/UnitConvertible.java | 77 +++++++ .../calculator/converter/UnitDimension.java | 83 +++++++ 10 files changed, 335 insertions(+), 226 deletions(-) create mode 100644 app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java create mode 100644 app/src/main/java/org/solovyev/android/calculator/converter/ConvertibleDimension.java create mode 100644 app/src/main/java/org/solovyev/android/calculator/converter/Named.java delete mode 100644 app/src/main/java/org/solovyev/android/calculator/converter/NamedDimension.java create mode 100644 app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java create mode 100644 app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseDimension.java create mode 100644 app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java create mode 100644 app/src/main/java/org/solovyev/android/calculator/converter/UnitDimension.java diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/Converter.java b/app/src/main/java/org/solovyev/android/calculator/converter/Converter.java index b3ed78c9..fb8641f2 100644 --- a/app/src/main/java/org/solovyev/android/calculator/converter/Converter.java +++ b/app/src/main/java/org/solovyev/android/calculator/converter/Converter.java @@ -8,7 +8,7 @@ import javax.annotation.Nonnull; import javax.measure.unit.Unit; final class Converter { - static int unitName(@Nonnull Unit unit, @Nonnull NamedDimension dimension) { + static int unitName(@Nonnull Unit unit, @Nonnull UnitDimension dimension) { final String id = Strings.nullToEmpty(unit.toString()); switch (dimension) { case TIME: diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java b/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java index 2c1126fb..35e6d0f0 100644 --- a/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/converter/ConverterFragment.java @@ -6,7 +6,6 @@ import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.annotation.StringRes; import android.support.design.widget.TextInputLayout; import android.support.v4.app.FragmentActivity; import android.support.v7.app.AlertDialog; @@ -20,41 +19,20 @@ import android.view.inputmethod.EditorInfo; import android.widget.*; import butterknife.Bind; import butterknife.ButterKnife; -import jscl.JsclMathEngine; -import jscl.NumeralBase; -import midpcalc.Real; import org.solovyev.android.calculator.*; import javax.annotation.Nonnull; import javax.inject.Inject; -import javax.measure.converter.UnitConverter; -import javax.measure.unit.NonSI; -import javax.measure.unit.SI; -import javax.measure.unit.Unit; -import java.util.*; +import java.util.Comparator; public class ConverterFragment extends BaseDialogFragment implements AdapterView.OnItemSelectedListener, View.OnFocusChangeListener, TextView.OnEditorActionListener, View.OnClickListener, TextWatcher { - // todo serso: better to provide a dimension-id pair as units might not be unique in different dimensions - @NonNull - private static final Set excludedUnits = new HashSet<>(Arrays.asList("year_sidereal", "year_calendar", "day_sidereal", "foot_survey_us", "me", "u")); - @NonNull - private static final Map> units = new HashMap<>(); private static final String STATE_SELECTION_FROM = "selection.from"; private static final String STATE_SELECTION_TO = "selection.to"; private static final String EXTRA_VALUE = "value"; private static final NamedItemComparator COMPARATOR = new NamedItemComparator(); - static { - for (Unit unit : SI.getInstance().getUnits()) { - addUnit(unit); - } - for (Unit unit : NonSI.getInstance().getUnits()) { - addUnit(unit); - } - } - @Inject Clipboard clipboard; @Inject @@ -75,31 +53,13 @@ public class ConverterFragment extends BaseDialogFragment EditText editTextTo; @Bind(R.id.converter_swap_button) ImageButton swapButton; - private ArrayAdapter> dimensionsAdapter; - private ArrayAdapter> adapterFrom; - private ArrayAdapter> adapterTo; + private ArrayAdapter> dimensionsAdapter; + private ArrayAdapter> adapterFrom; + private ArrayAdapter> adapterTo; private int pendingFromSelection = View.NO_ID; private int pendingToSelection = View.NO_ID; - private static void addUnit(@NonNull Unit unit) { - if (excludedUnits.contains(unit.toString())) { - return; - } - - final NamedDimension dimension = NamedDimension.of(unit); - if (dimension == null) { - return; - } - - List unitsInDimension = units.get(dimension); - if (unitsInDimension == null) { - unitsInDimension = new ArrayList<>(); - units.put(dimension, unitsInDimension); - } - unitsInDimension.add(MeasureUnit.create(unit)); - } - public static void show(@Nonnull FragmentActivity activity) { show(activity, 1d); } @@ -117,11 +77,6 @@ public class ConverterFragment extends BaseDialogFragment return new ArrayAdapter<>(context, R.layout.support_simple_spinner_dropdown_item); } - @Nonnull - private static NamedItem createNamedItem(@NonNull T item, @StringRes int name, @NonNull Context context) { - return new NamedItem<>(item, name == 0 ? item.toString() : context.getString(name)); - } - @Override protected void onPrepareDialog(@NonNull AlertDialog.Builder builder) { builder.setPositiveButton(R.string.c_use, null); @@ -144,9 +99,10 @@ public class ConverterFragment extends BaseDialogFragment ButterKnife.bind(this, view); dimensionsAdapter = makeAdapter(context); - for (NamedDimension dimension : NamedDimension.values()) { - dimensionsAdapter.add(named(dimension)); + for (ConvertibleDimension dimension : UnitDimension.values()) { + dimensionsAdapter.add(dimension.named(context)); } + dimensionsAdapter.add(NumeralBaseDimension.get().named(context)); adapterFrom = makeAdapter(context); adapterTo = makeAdapter(context); @@ -176,11 +132,6 @@ public class ConverterFragment extends BaseDialogFragment return view; } - @Nonnull - private NamedItem named(@Nonnull NamedDimension dimension) { - return createNamedItem(dimension, dimension.name); - } - @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); @@ -203,22 +154,22 @@ public class ConverterFragment extends BaseDialogFragment } } - private void onUnitFromChanged(@NonNull MyUnit unit) { + private void onUnitFromChanged(@NonNull Convertible unit) { final int dimensionPosition = dimensionsSpinner.getSelectedItemPosition(); updateUnitsTo(dimensionsAdapter.getItem(dimensionPosition).item, unit); convert(); } - private void onDimensionChanged(@NonNull NamedDimension dimension) { + private void onDimensionChanged(@NonNull ConvertibleDimension dimension) { updateUnitsFrom(dimension); updateUnitsTo(dimension, adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item); convert(); } - private void updateUnitsFrom(@NonNull NamedDimension dimension) { + private void updateUnitsFrom(@NonNull ConvertibleDimension dimension) { adapterFrom.setNotifyOnChange(false); adapterFrom.clear(); - for (MyUnit unit : units.get(dimension)) { + for (Convertible unit : dimension.getUnits()) { adapterFrom.add(unit.named(getActivity())); } adapterFrom.sort(COMPARATOR); @@ -228,8 +179,8 @@ public class ConverterFragment extends BaseDialogFragment pendingFromSelection = View.NO_ID; } - private void updateUnitsTo(@NonNull NamedDimension dimension, @NonNull MyUnit except) { - final MyUnit selectedUnit; + private void updateUnitsTo(@NonNull ConvertibleDimension dimension, @NonNull Convertible except) { + final Convertible selectedUnit; if (pendingToSelection > View.NO_ID) { selectedUnit = null; } else { @@ -238,7 +189,7 @@ public class ConverterFragment extends BaseDialogFragment } adapterTo.setNotifyOnChange(false); adapterTo.clear(); - for (MyUnit unit : units.get(dimension)) { + for (Convertible unit : dimension.getUnits()) { if (!except.equals(unit)) { adapterTo.add(unit.named(getActivity())); } @@ -248,7 +199,7 @@ public class ConverterFragment extends BaseDialogFragment adapterTo.notifyDataSetChanged(); if (selectedUnit != null && !except.equals(selectedUnit)) { for (int i = 0; i < adapterTo.getCount(); i++) { - final MyUnit unit = adapterTo.getItem(i).item; + final Convertible unit = adapterTo.getItem(i).item; if (unit.equals(selectedUnit)) { spinnerTo.setSelection(i); return; @@ -290,11 +241,9 @@ public class ConverterFragment extends BaseDialogFragment } try { - final MyUnit from = adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item; - final Object fromValue = from.parse(value); - final MyUnit to = adapterTo.getItem(spinnerTo.getSelectedItemPosition()).item; - final Object toValue = from.getConverterTo(to).convert(fromValue); - editTextTo.setText(to.format(toValue)); + final Convertible from = adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item; + final Convertible to = adapterTo.getItem(spinnerTo.getSelectedItemPosition()).item; + editTextTo.setText(from.convert(to, value)); clearError(labelFrom); } catch (RuntimeException e) { if (validate) { @@ -354,13 +303,13 @@ public class ConverterFragment extends BaseDialogFragment private void swap() { editTextFrom.setText(editTextTo.getText()); - final MyUnit oldFromUnit = adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item; - final MyUnit oldToUnit = adapterTo.getItem(spinnerTo.getSelectedItemPosition()).item; + final Convertible oldFromUnit = adapterFrom.getItem(spinnerFrom.getSelectedItemPosition()).item; + final Convertible oldToUnit = adapterTo.getItem(spinnerTo.getSelectedItemPosition()).item; pendingToSelection = -1; for (int i = 0; i < adapterFrom.getCount(); i++) { pendingToSelection++; - final MyUnit unit = adapterFrom.getItem(i).item; + final Convertible unit = adapterFrom.getItem(i).item; if (unit.equals(oldToUnit)) { pendingToSelection--; } else if (unit.equals(oldFromUnit)) { @@ -369,7 +318,7 @@ public class ConverterFragment extends BaseDialogFragment } for (int i = 0; i < adapterFrom.getCount(); i++) { - final MyUnit unit = adapterFrom.getItem(i).item; + final Convertible unit = adapterFrom.getItem(i).item; if (unit.equals(oldToUnit)) { spinnerFrom.setSelection(i); break; @@ -398,122 +347,10 @@ public class ConverterFragment extends BaseDialogFragment super.dismiss(); } - @Nonnull - private NamedItem createNamedItem(@NonNull T item, @StringRes int name) { - return createNamedItem(item, name, getActivity()); - } - - private interface MyUnit { - @NonNull - Object parse(@NonNull String value); - - @NonNull - String format(@NonNull Object value); - - @NonNull - MyConverter getConverterTo(@NonNull MyUnit to); - - @NonNull - NamedItem named(@NonNull Context context); - } - - private interface MyConverter { - Object convert(Object value); - } - - private static class NamedItem { - @NonNull - public final T item; - @NonNull - public final CharSequence name; - - private NamedItem(@NonNull T item, @Nonnull String name) { - this.item = item; - this.name = name; - } - + private static class NamedItemComparator implements Comparator> { @Override - public String toString() { - return name.toString(); - } - } - - private static class NamedItemComparator implements Comparator> { - @Override - public int compare(NamedItem lhs, NamedItem rhs) { + public int compare(Named lhs, Named rhs) { return lhs.toString().compareTo(rhs.toString()); } } - - private static final class MeasureUnit implements MyUnit { - @NonNull - final Unit unit; - - private MeasureUnit(@NonNull Unit unit) { - this.unit = unit; - } - - private static MeasureUnit create(@NonNull Unit unit) { - return new MeasureUnit(unit); - } - - @Override - public String toString() { - return unit.toString(); - } - - @NonNull - @Override - public Object parse(@NonNull String value) { - final String groupingSeparator = String.valueOf(JsclMathEngine.getInstance().getGroupingSeparator()); - if (!TextUtils.isEmpty(groupingSeparator)) { - value = value.replace(groupingSeparator, ""); - } - final long bits = new Real(value).toDoubleBits(); - return Double.longBitsToDouble(bits); - } - - @NonNull - @Override - public String format(@NonNull Object value) { - return JsclMathEngine.getInstance().format((Double) value, NumeralBase.dec); - } - - @NonNull - @Override - public MyConverter getConverterTo(@NonNull final MyUnit to) { - return new MyConverter() { - @Override - public Object convert(Object value) { - final UnitConverter converter = unit.getConverterTo(((MeasureUnit) to).unit); - return converter.convert((Double) value); - } - }; - } - - @NonNull - @Override - public NamedItem named(@Nonnull Context context) { - final NamedDimension dimension = NamedDimension.of(unit); - if (dimension == null) { - return createNamedItem((MyUnit) MeasureUnit.create(unit), 0, context); - } - return createNamedItem((MyUnit) MeasureUnit.create(unit), Converter.unitName(unit, dimension), context); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final MeasureUnit that = (MeasureUnit) o; - return unit.equals(that.unit); - - } - - @Override - public int hashCode() { - return unit.hashCode(); - } - } } diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java b/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java new file mode 100644 index 00000000..a2ccc9fb --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/converter/Convertible.java @@ -0,0 +1,12 @@ +package org.solovyev.android.calculator.converter; + +import android.content.Context; +import android.support.annotation.NonNull; + +interface Convertible { + @NonNull + String convert(@NonNull Convertible to, @NonNull String value); + + @NonNull + Named named(@NonNull Context context); +} diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/ConvertibleDimension.java b/app/src/main/java/org/solovyev/android/calculator/converter/ConvertibleDimension.java new file mode 100644 index 00000000..f33b6f1b --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/converter/ConvertibleDimension.java @@ -0,0 +1,14 @@ +package org.solovyev.android.calculator.converter; + +import android.content.Context; +import android.support.annotation.NonNull; + +import java.util.List; + +public interface ConvertibleDimension { + @NonNull + Named named(@NonNull Context context); + + @NonNull + List getUnits(); +} diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/Named.java b/app/src/main/java/org/solovyev/android/calculator/converter/Named.java new file mode 100644 index 00000000..c22059ad --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/converter/Named.java @@ -0,0 +1,49 @@ +package org.solovyev.android.calculator.converter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; + +import javax.annotation.Nonnull; + +class Named { + @NonNull + public final T item; + @NonNull + public final CharSequence name; + + private Named(@NonNull T item, @Nonnull String name) { + this.item = item; + this.name = name; + } + + @NonNull + static Named create(@NonNull T item, @Nonnull String name) { + return new Named(item, name); + } + + @NonNull + static Named create(@NonNull T item, @StringRes int name, @NonNull Context context) { + return create(item, name == 0 ? item.toString() : context.getString(name)); + } + + @Override + public String toString() { + return name.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final Named that = (Named) o; + return item.equals(that.item); + + } + + @Override + public int hashCode() { + return item.hashCode(); + } +} diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/NamedDimension.java b/app/src/main/java/org/solovyev/android/calculator/converter/NamedDimension.java deleted file mode 100644 index d2a7c5d2..00000000 --- a/app/src/main/java/org/solovyev/android/calculator/converter/NamedDimension.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.solovyev.android.calculator.converter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import org.solovyev.android.calculator.R; - -import javax.measure.unit.Dimension; -import javax.measure.unit.Unit; - -enum NamedDimension { - TIME(Dimension.TIME, R.string.cpp_converter_time), - AMOUNT_OF_SUBSTANCE(Dimension.AMOUNT_OF_SUBSTANCE, R.string.cpp_converter_amount_of_substance), - ELECTRIC_CURRENT(Dimension.ELECTRIC_CURRENT, R.string.cpp_converter_electric_current), - LENGTH(Dimension.LENGTH, R.string.cpp_converter_length), - MASS(Dimension.MASS, R.string.cpp_converter_mass), - TEMPERATURE(Dimension.TEMPERATURE, R.string.cpp_converter_temperature); - - @NonNull - public final Dimension dimension; - @StringRes - public final int name; - - NamedDimension(@NonNull Dimension dimension, @StringRes int name) { - this.dimension = dimension; - this.name = name; - } - - @Nullable - public static NamedDimension of(@NonNull Unit unit) { - for (NamedDimension myDimension : values()) { - if (myDimension.dimension.equals(unit.getDimension())) { - return myDimension; - } - } - return null; - } -} diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java new file mode 100644 index 00000000..d1665237 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseConvertible.java @@ -0,0 +1,32 @@ +package org.solovyev.android.calculator.converter; + +import android.content.Context; +import android.support.annotation.NonNull; +import jscl.NumeralBase; + +public class NumeralBaseConvertible implements Convertible { + + @NonNull + private final NumeralBase base; + + public NumeralBaseConvertible(@NonNull NumeralBase base) { + this.base = base; + } + + @NonNull + @Override + public String convert(@NonNull Convertible to, @NonNull String value) { + try { + base.toBigInteger(value); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + return null; + } + + @NonNull + @Override + public Named named(@NonNull Context context) { + return Named.create(this, base.name()); + } +} diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseDimension.java b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseDimension.java new file mode 100644 index 00000000..ce447744 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/converter/NumeralBaseDimension.java @@ -0,0 +1,43 @@ +package org.solovyev.android.calculator.converter; + +import android.content.Context; +import android.support.annotation.NonNull; +import jscl.NumeralBase; +import org.solovyev.android.calculator.R; + +import java.util.ArrayList; +import java.util.List; + +public class NumeralBaseDimension implements ConvertibleDimension { + + @NonNull + private static final NumeralBaseDimension INSTANCE = new NumeralBaseDimension(); + @NonNull + private final List units = new ArrayList<>(); + + { + for (NumeralBase base : NumeralBase.values()) { + units.add(new NumeralBaseConvertible(base)); + } + } + + private NumeralBaseDimension() { + } + + @NonNull + public static ConvertibleDimension get() { + return INSTANCE; + } + + @NonNull + @Override + public Named named(@NonNull Context context) { + return Named.create(this, R.string.cpp_radix, context); + } + + @NonNull + @Override + public List getUnits() { + return units; + } +} diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java b/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java new file mode 100644 index 00000000..90d81887 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/converter/UnitConvertible.java @@ -0,0 +1,77 @@ +package org.solovyev.android.calculator.converter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.text.TextUtils; +import jscl.JsclMathEngine; +import jscl.NumeralBase; +import midpcalc.Real; + +import javax.annotation.Nonnull; +import javax.measure.unit.Unit; + +final class UnitConvertible implements Convertible { + @NonNull + private final Unit unit; + + private UnitConvertible(@NonNull Unit unit) { + this.unit = unit; + } + + @NonNull + static UnitConvertible create(@NonNull Unit unit) { + return new UnitConvertible(unit); + } + + @Override + public String toString() { + return unit.toString(); + } + + public double parse(@NonNull String value) { + final String groupingSeparator = String.valueOf(JsclMathEngine.getInstance().getGroupingSeparator()); + if (!TextUtils.isEmpty(groupingSeparator)) { + value = value.replace(groupingSeparator, ""); + } + final long bits = new Real(value).toDoubleBits(); + return Double.longBitsToDouble(bits); + } + + @NonNull + public String format(double value) { + return JsclMathEngine.getInstance().format(value, NumeralBase.dec); + } + + @NonNull + @Override + public String convert(@NonNull Convertible to, @NonNull String value) { + final double from = parse(value); + final double converted = unit.getConverterTo(((UnitConvertible) to).unit).convert(from); + return format(converted); + } + + @NonNull + @Override + public Named named(@Nonnull Context context) { + final UnitDimension dimension = UnitDimension.of(unit); + if (dimension == null) { + return Named.create(this, 0, context); + } + return Named.create(this, Converter.unitName(unit, dimension), context); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final UnitConvertible that = (UnitConvertible) o; + return unit.equals(that.unit); + + } + + @Override + public int hashCode() { + return unit.hashCode(); + } +} diff --git a/app/src/main/java/org/solovyev/android/calculator/converter/UnitDimension.java b/app/src/main/java/org/solovyev/android/calculator/converter/UnitDimension.java new file mode 100644 index 00000000..6dc91974 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/calculator/converter/UnitDimension.java @@ -0,0 +1,83 @@ +package org.solovyev.android.calculator.converter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import org.solovyev.android.calculator.R; + +import javax.measure.unit.Dimension; +import javax.measure.unit.NonSI; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; +import java.util.*; + +enum UnitDimension implements ConvertibleDimension { + TIME(Dimension.TIME, R.string.cpp_converter_time), + AMOUNT_OF_SUBSTANCE(Dimension.AMOUNT_OF_SUBSTANCE, R.string.cpp_converter_amount_of_substance), + ELECTRIC_CURRENT(Dimension.ELECTRIC_CURRENT, R.string.cpp_converter_electric_current), + LENGTH(Dimension.LENGTH, R.string.cpp_converter_length), + MASS(Dimension.MASS, R.string.cpp_converter_mass), + TEMPERATURE(Dimension.TEMPERATURE, R.string.cpp_converter_temperature); + + // todo serso: better to provide a dimension-id pair as units might not be unique in different dimensions + @NonNull + private static final Set excludedUnits = new HashSet<>(Arrays.asList("year_sidereal", "year_calendar", "day_sidereal", "foot_survey_us", "me", "u")); + @NonNull + private static final Map> units = new HashMap<>(); + + static { + for (Unit unit : SI.getInstance().getUnits()) { + addUnit(unit); + } + for (Unit unit : NonSI.getInstance().getUnits()) { + addUnit(unit); + } + } + + @NonNull + public final Dimension dimension; + @StringRes + public final int name; + UnitDimension(@NonNull Dimension dimension, @StringRes int name) { + this.dimension = dimension; + this.name = name; + } + + private static void addUnit(@NonNull Unit unit) { + if (excludedUnits.contains(unit.toString())) { + return; + } + + final Dimension dimension = unit.getDimension(); + List unitsInDimension = units.get(dimension); + if (unitsInDimension == null) { + unitsInDimension = new ArrayList<>(); + units.put(dimension, unitsInDimension); + } + unitsInDimension.add(UnitConvertible.create(unit)); + } + + @Nullable + public static UnitDimension of(@NonNull Unit unit) { + for (UnitDimension myDimension : values()) { + if (myDimension.dimension.equals(unit.getDimension())) { + return myDimension; + } + } + return null; + } + + + @NonNull + @Override + public Named named(@NonNull Context context) { + return Named.create(this, name, context); + } + + @NonNull + @Override + public List getUnits() { + return units.get(dimension); + } +}