001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2020, 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 javax.measure.Quantity.Scale.ABSOLUTE; 033 034import java.math.BigDecimal; 035import java.math.BigInteger; 036import java.util.Objects; 037 038import javax.measure.MeasurementException; 039import javax.measure.Quantity; 040import javax.measure.Quantity.Scale; 041import javax.measure.Unit; 042import javax.measure.format.MeasurementParseException; 043 044import tech.units.indriya.ComparableQuantity; 045import tech.units.indriya.format.AbstractQuantityFormat; 046import tech.units.indriya.format.SimpleQuantityFormat; 047import tech.units.indriya.function.MixedRadix; 048 049/** 050 * Singleton class for accessing {@link Quantity} instances. 051 * 052 * @version 1.10, April 20, 2019 053 * @author keilw 054 * @author otaviojava 055 * @since 1.0 056 */ 057public final class Quantities { 058 /** 059 * Private singleton constructor. 060 */ 061 private Quantities() { 062 } 063 064 /** 065 * Returns the {@link #valueOf(java.math.BigDecimal, javax.measure.unit.Unit) 066 * decimal} quantity of unknown type corresponding to the specified 067 * representation. This method can be used to parse dimensionless 068 * quantities.<br> 069 * <code> 070 * Quantity<Dimensionless> proportion = Quantities.getQuantity("0.234").asType(Dimensionless.class); 071 * </code> 072 * 073 * <p> 074 * Note: This method handles only Locale-neutral quantity formatting and parsing 075 * are handled by the {@link AbstractQuantityFormat} class and its subclasses. 076 * </p> 077 * 078 * @param csq the decimal value and its unit (if any) separated by space(s). 079 * @return <code>QuantityFormat.getInstance(LOCALE_NEUTRAL).parse(csq)</code> 080 */ 081 public static Quantity<?> getQuantity(CharSequence csq) { 082 try { 083 return SimpleQuantityFormat.getInstance("n u~ ").parse(csq); 084 } catch (MeasurementParseException e) { 085 throw new IllegalArgumentException(e.getParsedString()); 086 } 087 } 088 089 /** 090 * Returns the scalar quantity. When the {@link Number} was {@link BigDecimal} 091 * or {@link BigInteger} will uses {@link DecimalQuantity}, when the 092 * {@link Number} was {@link Double} will {@link DoubleQuantity} otherwise will 093 * {@link NumberQuantity}. in the specified unit. 094 * 095 * @param value the measurement value. 096 * @param unit the measurement unit. 097 * @param scale the measurement scale. 098 * @return the corresponding <code>numeric</code> quantity. 099 * @throws NullPointerException if value, unit or scale were null 100 * @throws MeasurementException if unit is a MixedUnit 101 * @since 2.0 102 */ 103 public static <Q extends Quantity<Q>> ComparableQuantity<Q> getQuantity(Number value, Unit<Q> unit, Scale scale) { 104 Objects.requireNonNull(value); 105 Objects.requireNonNull(unit); 106 Objects.requireNonNull(scale); 107 return new NumberQuantity<>(value, unit, scale); 108 } 109 110 /** 111 * Returns the scalar quantity. When the {@link Number} was {@link BigDecimal} 112 * or {@link BigInteger} will uses {@link DecimalQuantity}, when the 113 * {@link Number} was {@link Double} will {@link DoubleQuantity} otherwise will 114 * {@link NumberQuantity}. in the specified unit. 115 * 116 * @param value the measurement value. 117 * @param unit the measurement unit. 118 * @return the corresponding <code>numeric</code> quantity. 119 * @throws NullPointerException when value or unit were null 120 */ 121 public static <Q extends Quantity<Q>> ComparableQuantity<Q> getQuantity(Number value, Unit<Q> unit) { 122 return getQuantity(value, unit, ABSOLUTE); 123 } 124 125 /** 126 * Returns the mixed radix values and units combined into a single quantity. 127 * When the {@link Number} was {@link BigDecimal} or {@link BigInteger} will 128 * uses {@link DecimalQuantity}, when the {@link Number} was {@link Double} will 129 * {@link DoubleQuantity} otherwise will {@link NumberQuantity}. in the 130 * specified unit. 131 * 132 * @param values the measurement values. 133 * @param units the measurement units. 134 * @param scale the measurement scale. 135 * @return the corresponding quantity. 136 * @throws NullPointerException if value or scale were null 137 * @throws IllegalArgumentException if the size of the values array does not 138 * match that of units. 139 * @since 2.0 140 */ 141 public static <Q extends Quantity<Q>> Quantity<Q> getQuantity(Number[] values, Unit<Q>[] units, Scale scale) { 142 Objects.requireNonNull(values); 143 Objects.requireNonNull(units); 144 if (values.length == units.length) { 145 return MixedRadix.of(units).createQuantity(values, scale); 146 } else { 147 throw new IllegalArgumentException( 148 String.format("%s values don't match %s units", values.length, units.length)); 149 } 150 } 151 152 /** 153 * Returns the mixed radix values and units combined into a single quantity in 154 * the {@code ABSOLUTE} scale. 155 * 156 * @param values the measurement values. 157 * @param units the measurement units. 158 * @return the corresponding quantity. 159 * @throws NullPointerException if value or unit were null 160 * @throws IllegalArgumentException if the size of the values array does not 161 * match that of units. 162 * @since 2.0 163 */ 164 @SafeVarargs 165 public static <Q extends Quantity<Q>> Quantity<Q> getQuantity(Number[] values, Unit<Q>... units) { 166 return getQuantity(values, units, ABSOLUTE); 167 } 168 169 /** 170 * Returns the mixed radix values and units as {@link CompoundQuantity} in the 171 * specified scale. 172 * 173 * @param values the measurement values. 174 * @param units the measurement units. 175 * @param scale the measurement scale. 176 * @return the corresponding compound quantity. 177 * @throws NullPointerException if values, units or scale were null 178 * @throws IllegalArgumentException if the size of the values array does not 179 * match that of units. 180 * @since 2.0 181 */ 182 public static <Q extends Quantity<Q>> CompoundQuantity<Q> getCompoundQuantity(Number[] values, Unit<Q>[] units, 183 Scale scale) { 184 Objects.requireNonNull(values); 185 Objects.requireNonNull(units); 186 if (values.length == units.length) { 187 return MixedRadix.of(units).createCompoundQuantity(values, scale); 188 } else { 189 throw new IllegalArgumentException( 190 String.format("%s values don't match %s units", values.length, units.length)); 191 } 192 } 193 194 /** 195 * Returns the mixed radix values and units as {@link CompoundQuantity} in the 196 * {@code ABSOLUTE} scale. 197 * 198 * @param values the measurement values. 199 * @param units the measurement units. 200 * @return the corresponding compound quantity. 201 * @throws NullPointerException if values, units or scale were null 202 * @throws IllegalArgumentException if the size of the values array does not 203 * match that of units. 204 * @since 2.0 205 */ 206 public static <Q extends Quantity<Q>> CompoundQuantity<Q> getCompoundQuantity(final Number[] values, 207 final Unit<Q>[] units) { 208 return getCompoundQuantity(values, units, ABSOLUTE); 209 } 210}