001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2018, Jean-Marie Dautelle, Werner Keil, Otavio Santana. 004 * 005 * All rights reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without modification, 008 * are permitted provided that the following conditions are met: 009 * 010 * 1. Redistributions of source code must retain the above copyright notice, 011 * this list of conditions and the following disclaimer. 012 * 013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 014 * and the following disclaimer in the documentation and/or other materials provided with the distribution. 015 * 016 * 3. Neither the name of JSR-385, Indriya nor the names of their contributors may be used to endorse or promote products 017 * derived from this software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package tech.units.indriya.quantity; 031 032import static tech.units.indriya.unit.Units.AMPERE; 033import static tech.units.indriya.unit.Units.BECQUEREL; 034import static tech.units.indriya.unit.Units.CANDELA; 035import static tech.units.indriya.unit.Units.COULOMB; 036import static tech.units.indriya.unit.Units.CUBIC_METRE; 037import static tech.units.indriya.unit.Units.FARAD; 038import static tech.units.indriya.unit.Units.GRAY; 039import static tech.units.indriya.unit.Units.HENRY; 040import static tech.units.indriya.unit.Units.HERTZ; 041import static tech.units.indriya.unit.Units.JOULE; 042import static tech.units.indriya.unit.Units.KATAL; 043import static tech.units.indriya.unit.Units.KELVIN; 044import static tech.units.indriya.unit.Units.KILOGRAM; 045import static tech.units.indriya.unit.Units.LUMEN; 046import static tech.units.indriya.unit.Units.LUX; 047import static tech.units.indriya.unit.Units.METRE; 048import static tech.units.indriya.unit.Units.METRE_PER_SECOND; 049import static tech.units.indriya.unit.Units.METRE_PER_SQUARE_SECOND; 050import static tech.units.indriya.unit.Units.MOLE; 051import static tech.units.indriya.unit.Units.NEWTON; 052import static tech.units.indriya.unit.Units.OHM; 053import static tech.units.indriya.unit.Units.PASCAL; 054import static tech.units.indriya.unit.Units.RADIAN; 055import static tech.units.indriya.unit.Units.SECOND; 056import static tech.units.indriya.unit.Units.SIEMENS; 057import static tech.units.indriya.unit.Units.SIEVERT; 058import static tech.units.indriya.unit.Units.SQUARE_METRE; 059import static tech.units.indriya.unit.Units.STERADIAN; 060import static tech.units.indriya.unit.Units.TESLA; 061import static tech.units.indriya.unit.Units.VOLT; 062import static tech.units.indriya.unit.Units.WATT; 063import static tech.units.indriya.unit.Units.WEBER; 064 065import java.util.HashMap; 066import java.util.Map; 067import java.util.Objects; 068import java.util.concurrent.ConcurrentHashMap; 069import java.util.logging.Level; 070import java.util.logging.Logger; 071 072import javax.measure.Quantity; 073import javax.measure.Unit; 074import javax.measure.quantity.Acceleration; 075import javax.measure.quantity.AmountOfSubstance; 076import javax.measure.quantity.Angle; 077import javax.measure.quantity.Area; 078import javax.measure.quantity.CatalyticActivity; 079import javax.measure.quantity.Dimensionless; 080import javax.measure.quantity.ElectricCapacitance; 081import javax.measure.quantity.ElectricCharge; 082import javax.measure.quantity.ElectricConductance; 083import javax.measure.quantity.ElectricCurrent; 084import javax.measure.quantity.ElectricInductance; 085import javax.measure.quantity.ElectricPotential; 086import javax.measure.quantity.ElectricResistance; 087import javax.measure.quantity.Energy; 088import javax.measure.quantity.Force; 089import javax.measure.quantity.Frequency; 090import javax.measure.quantity.Illuminance; 091import javax.measure.quantity.Length; 092import javax.measure.quantity.LuminousFlux; 093import javax.measure.quantity.LuminousIntensity; 094import javax.measure.quantity.MagneticFlux; 095import javax.measure.quantity.MagneticFluxDensity; 096import javax.measure.quantity.Mass; 097import javax.measure.quantity.Power; 098import javax.measure.quantity.Pressure; 099import javax.measure.quantity.RadiationDoseAbsorbed; 100import javax.measure.quantity.RadiationDoseEffective; 101import javax.measure.quantity.Radioactivity; 102import javax.measure.quantity.SolidAngle; 103import javax.measure.quantity.Speed; 104import javax.measure.quantity.Temperature; 105import javax.measure.quantity.Time; 106import javax.measure.quantity.Volume; 107import javax.measure.spi.QuantityFactory; 108 109import tech.units.indriya.AbstractUnit; 110 111/** 112 * A factory producing simple quantities instances (tuples {@link Number}/ {@link Unit}).<br> 113 * 114 * For example:<br> 115 * <code> 116 * Mass m = DefaultQuantityFactory.getInstance(Mass.class).create(23.0, KILOGRAM); // 23.0 kg<br> 117 * Time m = DefaultQuantityFactory.getInstance(Time.class).create(124, MILLI(SECOND)); // 124 ms 118 * </code> 119 * 120 * @param <Q> 121 * The type of the quantity. 122 * 123 * @author <a href="mailto:martin.desruisseaux@geomatys.com">Martin Desruisseaux</a> 124 * @author <a href="mailto:units@catmedia.us">Werner Keil</a> 125 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 126 * @author <a href="mailto:otaviojava@java.net">Otavio Santana</a> 127 * @version 1.2.2, $Date: 2018-07-06 $ 128 * @since 1.0 129 */ 130public class DefaultQuantityFactory<Q extends Quantity<Q>> implements QuantityFactory<Q> { 131 @SuppressWarnings("rawtypes") 132 static final Map<Class, QuantityFactory> INSTANCES = new HashMap<>(); 133 134 static final Logger logger = Logger.getLogger(DefaultQuantityFactory.class.getName()); 135 136 static final Level LOG_LEVEL = Level.FINE; 137 138 /** 139 * The type of the quantities created by this factory. 140 */ 141 private final Class<Q> type; 142 143 /** 144 * The system unit for quantities created by this factory. 145 */ 146 private final Unit<Q> systemUnit; 147 148 @SuppressWarnings("rawtypes") 149 private static final Map<Class, Unit> CLASS_TO_SYSTEM_UNIT = new ConcurrentHashMap<>(); 150 151 static { 152 CLASS_TO_SYSTEM_UNIT.put(Dimensionless.class, AbstractUnit.ONE); 153 CLASS_TO_SYSTEM_UNIT.put(ElectricCurrent.class, AMPERE); 154 CLASS_TO_SYSTEM_UNIT.put(LuminousIntensity.class, CANDELA); 155 CLASS_TO_SYSTEM_UNIT.put(Temperature.class, KELVIN); 156 CLASS_TO_SYSTEM_UNIT.put(Mass.class, KILOGRAM); 157 CLASS_TO_SYSTEM_UNIT.put(Length.class, METRE); 158 CLASS_TO_SYSTEM_UNIT.put(AmountOfSubstance.class, MOLE); 159 CLASS_TO_SYSTEM_UNIT.put(Time.class, SECOND); 160 CLASS_TO_SYSTEM_UNIT.put(Angle.class, RADIAN); 161 CLASS_TO_SYSTEM_UNIT.put(SolidAngle.class, STERADIAN); 162 CLASS_TO_SYSTEM_UNIT.put(Frequency.class, HERTZ); 163 CLASS_TO_SYSTEM_UNIT.put(Force.class, NEWTON); 164 CLASS_TO_SYSTEM_UNIT.put(Pressure.class, PASCAL); 165 CLASS_TO_SYSTEM_UNIT.put(Energy.class, JOULE); 166 CLASS_TO_SYSTEM_UNIT.put(Power.class, WATT); 167 CLASS_TO_SYSTEM_UNIT.put(ElectricCharge.class, COULOMB); 168 CLASS_TO_SYSTEM_UNIT.put(ElectricPotential.class, VOLT); 169 CLASS_TO_SYSTEM_UNIT.put(ElectricCapacitance.class, FARAD); 170 CLASS_TO_SYSTEM_UNIT.put(ElectricResistance.class, OHM); 171 CLASS_TO_SYSTEM_UNIT.put(ElectricConductance.class, SIEMENS); 172 CLASS_TO_SYSTEM_UNIT.put(MagneticFlux.class, WEBER); 173 CLASS_TO_SYSTEM_UNIT.put(MagneticFluxDensity.class, TESLA); 174 CLASS_TO_SYSTEM_UNIT.put(ElectricInductance.class, HENRY); 175 CLASS_TO_SYSTEM_UNIT.put(LuminousFlux.class, LUMEN); 176 CLASS_TO_SYSTEM_UNIT.put(Illuminance.class, LUX); 177 CLASS_TO_SYSTEM_UNIT.put(Radioactivity.class, BECQUEREL); 178 CLASS_TO_SYSTEM_UNIT.put(RadiationDoseAbsorbed.class, GRAY); 179 CLASS_TO_SYSTEM_UNIT.put(RadiationDoseEffective.class, SIEVERT); 180 CLASS_TO_SYSTEM_UNIT.put(CatalyticActivity.class, KATAL); 181 CLASS_TO_SYSTEM_UNIT.put(Speed.class, METRE_PER_SECOND); 182 CLASS_TO_SYSTEM_UNIT.put(Acceleration.class, METRE_PER_SQUARE_SECOND); 183 CLASS_TO_SYSTEM_UNIT.put(Area.class, SQUARE_METRE); 184 CLASS_TO_SYSTEM_UNIT.put(Volume.class, CUBIC_METRE); 185 } 186 187 @SuppressWarnings("unchecked") 188 private DefaultQuantityFactory(Class<Q> quantity) { 189 type = quantity; 190 systemUnit = CLASS_TO_SYSTEM_UNIT.get(type); 191 } 192 193 /** 194 * Returns the default instance for the specified quantity type. 195 * 196 * @param <Q> 197 * The type of the quantity 198 * @param type 199 * the quantity type 200 * @return the quantity factory for the specified type 201 */ 202 @SuppressWarnings("unchecked") 203 public static <Q extends Quantity<Q>> QuantityFactory<Q> getInstance(final Class<Q> type) { 204 logger.log(LOG_LEVEL, "Type: " + type + ": " + type.isInterface()); 205 QuantityFactory<Q> factory; 206 factory = INSTANCES.get(type); 207 if (factory != null) { 208 return factory; 209 } 210 if (!Quantity.class.isAssignableFrom(type)) { 211 // This exception is not documented because it should never 212 // happen if the 213 // user don't try to trick the Java generic types system with 214 // unsafe cast. 215 throw new ClassCastException(); 216 } 217 factory = new DefaultQuantityFactory<Q>(type); 218 INSTANCES.put(type, factory); 219 return factory; 220 } 221 222 public String toString() { 223 return getClass().getName() + " <" + type.getName() + '>'; 224 } 225 226 public boolean equals(Object obj) { 227 if (DefaultQuantityFactory.class.isInstance(obj)) { 228 @SuppressWarnings("rawtypes") 229 DefaultQuantityFactory other = DefaultQuantityFactory.class.cast(obj); 230 return Objects.equals(type, other.type); 231 } 232 return false; 233 } 234 235 public int hashCode() { 236 return type.hashCode(); 237 } 238 239 public Quantity<Q> create(Number value, Unit<Q> unit) { 240 return Quantities.getQuantity(value, unit); 241 } 242 243 public Unit<Q> getSystemUnit() { 244 return systemUnit; 245 } 246}