/** * */ package cz.cuni.mff.peckam.java.origamist.model; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.text.MessageFormat; import java.util.Hashtable; import java.util.Locale; import java.util.ResourceBundle; import cz.cuni.mff.peckam.java.origamist.model.jaxb.Unit; import cz.cuni.mff.peckam.java.origamist.services.ServiceLocator; import cz.cuni.mff.peckam.java.origamist.services.interfaces.ConfigurationManager; import cz.cuni.mff.peckam.java.origamist.utils.LocalizedString; import cz.cuni.mff.peckam.java.origamist.utils.ParametrizedLocalizedString; /** * This class provides additional functionality of the Unit enum. * * In localization patterns you are given a number indicating which unit is to be used. The given number is equal the * unit's ordinal() value. * * @author Martin Pecka */ public class UnitHelper { /** * This associative array holds lengths of all units in meters */ protected static Hashtable<Unit, Double> inMeters = new Hashtable<Unit, Double>(); /** The resource bundle for getting the unit names. */ private static ResourceBundle messages; static { inMeters.put(Unit.MM, 0.001d); inMeters.put(Unit.CM, 0.01d); inMeters.put(Unit.M, 1.0d); inMeters.put(Unit.KM, 1000.0d); inMeters.put(Unit.REL, Double.NaN); inMeters.put(Unit.INCH, 0.0254d); inMeters.put(Unit.FOOT, 0.3048d); inMeters.put(Unit.MILE, 1609.344d); PropertyChangeListener l = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { messages = ResourceBundle.getBundle("application", (Locale) evt.getNewValue()); } }; ServiceLocator.get(ConfigurationManager.class).get().addPropertyChangeListener("locale", l); l.propertyChange(new PropertyChangeEvent(new Object(), "locale", null, ServiceLocator .get(ConfigurationManager.class).get().getLocale())); } /** * Convert the value given in unit from to a value in unit to. * * If any of the units is REL, return <code>Double.NaN</code>. If you need to convert a relative value, use the * overload with a reference Unit and dimension. * * @param from The unit of the given value. * @param to The unit we want result to be in. * @param value The value in the from unit. * @return The corresponding value in the to unit. */ public static Double convertTo(Unit from, Unit to, double value) { if (Double.isNaN(inMeters.get(from)) || Double.isNaN(inMeters.get(to))) return Double.NaN; return value * inMeters.get(from) / inMeters.get(to); } /** * Convert the value given in unit from to a value in unit to. * * If any of the units is REL, use the given reference dimension. * * @param from The unit of the given value. * @param to The unit we want result to be in. * @param value The value in the from unit. * @param referenceUnit The unit the reference dimension has. * @param referenceLength The length of the reference unit. * @return The corresponding value in the to unit. * * @throws IllegalStateException If trying to convert to/from relative units without the reference dimension set. */ public static Double convertTo(Unit from, Unit to, double value, Unit referenceUnit, Double referenceLength) throws IllegalStateException { Double res = convertTo(from, to, value); if (!Double.isNaN(res)) return res; try { if (from == Unit.REL && referenceUnit != null && referenceLength != null) { return convertTo(referenceUnit, to, value * referenceLength); } else if (to == Unit.REL) { return convertTo(from, referenceUnit, value) / referenceLength; } else { throw new NullPointerException(); } } catch (NullPointerException e) { throw new IllegalStateException( "Trying to convert to/from a relative unit, but the reference dimension is <code>null</code>."); } } /** * Return the human-friendly name of the unit (eg. <code>mile</code> or <code>meter</code>). * * @param unit The unit to get the name of. * @return The human-friendly name of the unit (eg. <code>mile</code> or <code>meter</code>). */ public static String getUnitName(Unit unit) { return messages.getString("units." + unit.toString()); } /** * Return the human-friendly name of the unit (eg. <code>mile</code> or <code>meter</code>). * * @param unit The unit to get the name of. * @param asLocalizedString Only signature differentiating parameter, has no other meaning. * @return The human-friendly name of the unit (eg. <code>mile</code> or <code>meter</code>). */ public static LocalizedString getUnitName(Unit unit, boolean asLocalizedString) { return new LocalizedString("application", "units." + unit.toString()); } /** * Return the mark (abbreviation) of the unit (eg. <code>mm</code> or <code>″</code>). * * @param unit The unit to get the mark of. * @return The mark (abbreviation) of the unit (eg. <code>mm</code> or <code>″</code>). */ public static String getUnitMark(Unit unit) { return messages.getString("units." + unit.toString() + ".mark"); } /** * Return the mark (abbreviation) of the unit (eg. <code>mm</code> or <code>″</code>). * * @param unit The unit to get the mark of. * @param asLocalizedString Only signature differentiating parameter, has no other meaning. * @return The mark (abbreviation) of the unit (eg. <code>mm</code> or <code>″</code>). */ public static LocalizedString getUnitMark(Unit unit, boolean asLocalizedString) { return new LocalizedString("application", "units." + unit.toString() + ".mark"); } /** * Return the description of the unit. * * The description would usually contain the name and the mark of the unit. * * @param unit The unit to get the description of. * @return The description of the unit. */ public static String getUnitDescription(Unit unit) { return String.format(messages.getString("units.description"), getUnitName(unit), getUnitMark(unit)); } /** * Return the description of the unit. * * The description would usually contain the name and the mark of the unit. * * @param unit The unit to get the description of. * @param asLocalizedString Only signature differentiating parameter, has no other meaning. * @return The description of the unit. */ public static LocalizedString getUnitDescription(Unit unit, boolean asLocalizedString) { return new ParametrizedLocalizedString("application", "units.description", getUnitName(unit, true), getUnitMark(unit, true)); } /** * Return the formatted string that contains the given value and the unit's mark. * * @param unit The unit to use. * @param value The value to display. * @return The formatted string that contains the given value and the unit's mark. */ public static String formatUnit(Unit unit, double value) { return MessageFormat.format(messages.getString("units." + unit.toString() + ".format"), new Double(value)); } /** * Return the formatted string that contains the given value and the unit's mark. * * @param unit The unit to use. * @param value The value to display. * @param asLocalizedString Only signature differentiating parameter, has no other meaning. * @return The formatted string that contains the given value and the unit's mark. */ public static LocalizedString formatUnit(Unit unit, double value, boolean asLocalizedString) { return new ParametrizedLocalizedString("application", "units." + unit.toString() + ".format", new Double(value)); } }