001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2023, 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.Quantity; 039import javax.measure.Quantity.Scale; 040import javax.measure.Unit; 041 042import tech.units.indriya.ComparableQuantity; 043import tech.units.indriya.format.SimpleQuantityFormat; 044import tech.units.indriya.function.MixedRadix; 045 046/** 047 * Facade to access {@link Quantity} instances. 048 * 049 * @version 2.4, June 5, 2023 050 * @author Werner Keil 051 * @author Otavio Santana 052 * @since 1.0 053 */ 054public final class Quantities { 055 /** 056 * Private singleton constructor. 057 */ 058 private Quantities() { 059 } 060 061 /** 062 * Returns the scalar quantity of unknown type corresponding to the specified 063 * representation. This method can be used to parse {@link MixedQuantity mixed} 064 * quantities. All of these expressions:<br> 065 * <code> 066 * Quantity<Length> height = Quantities.getQuantity("1.70 m").asType(Length.class);<br> 067 * Quantity<Length> heightinCm = Quantities.getQuantity("170 cm").asType(Length.class);<br> 068 * Quantity<Length> heightMixed = Quantities.getQuantity("1 m 70 cm").asType(Length.class); 069 * </code> 070 * are equally supported. 071 * 072 * <p> 073 * <b>Note:</b> This method handles only <code>Locale</code>-neutral quantity formatting and parsing 074 * are handled by the {@link SimpleQuantityFormat} class.<br> 075 * Due to the versatile parsing of this method recognizing both single and mixed quantities, a unit must be provided, otherwise it'll fail. 076 * If you need to parse a unit-less quantity, please use the <code>parse()</code> method of {@link tech.units.indriya.AbstractQuantity AbstractQuantity} instead. 077 * </p> 078 * 079 * @param csq the decimal value(s) and unit(s) separated by space(s). 080 * @return <code>SimpleQuantityFormat.getInstance("n u~ ").parse(csq)</code> 081 * @throws IllegalArgumentException if no unit part was provided to parse 082 */ 083 public static Quantity<?> getQuantity(CharSequence csq) { 084 //try { 085 return SimpleQuantityFormat.getInstance("n u~ ").parse(csq); 086 //} catch (MeasurementParseException e) { 087// throw new IllegalArgumentException(e.getParsedString()); 088 // } 089 } 090 091 /** 092 * Returns the scalar quantity. When the {@link Number} was {@link BigDecimal} 093 * or {@link BigInteger} will uses {@link DecimalQuantity}, when the 094 * {@link Number} was {@link Double} will {@link DoubleQuantity} otherwise will 095 * {@link NumberQuantity}. in the specified unit. 096 * 097 * @param value the measurement value. 098 * @param unit the measurement unit. 099 * @param scale the measurement scale. 100 * @return the corresponding <code>numeric</code> quantity. 101 * @throws NullPointerException if value, unit or scale were null 102 * @since 2.0 103 */ 104 public static <Q extends Quantity<Q>> ComparableQuantity<Q> getQuantity(Number value, Unit<Q> unit, Scale scale) { 105 Objects.requireNonNull(value); 106 Objects.requireNonNull(unit); 107 Objects.requireNonNull(scale); 108 return new NumberQuantity<>(value, unit, scale); 109 } 110 111 /** 112 * Returns the scalar quantity. When the {@link Number} was {@link BigDecimal} 113 * or {@link BigInteger} will uses {@link DecimalQuantity}, when the 114 * {@link Number} was {@link Double} will {@link DoubleQuantity} otherwise will 115 * {@link NumberQuantity}. in the specified unit. 116 * 117 * @param value the measurement value. 118 * @param unit the measurement unit. 119 * @return the corresponding <code>numeric</code> quantity. 120 * @throws NullPointerException when value or unit were null 121 */ 122 public static <Q extends Quantity<Q>> ComparableQuantity<Q> getQuantity(Number value, Unit<Q> unit) { 123 return getQuantity(value, unit, ABSOLUTE); 124 } 125 126 /** 127 * Returns the mixed radix values and units combined into a single quantity. 128 * When the {@link Number} was {@link BigDecimal} or {@link BigInteger} will 129 * uses {@link DecimalQuantity}, when the {@link Number} was {@link Double} will 130 * {@link DoubleQuantity} otherwise will {@link NumberQuantity}. in the 131 * specified unit. 132 * 133 * @param values the measurement values. 134 * @param units the measurement units. 135 * @param scale the measurement scale. 136 * @return the corresponding quantity. 137 * @throws NullPointerException if values or scale were null 138 * @throws IllegalArgumentException if the size of the values array does not 139 * match that of units. 140 * @since 2.0 141 */ 142 public static <Q extends Quantity<Q>> Quantity<Q> getQuantity(Number[] values, Unit<Q>[] units, Scale scale) { 143 Objects.requireNonNull(values); 144 Objects.requireNonNull(units); 145 if (values.length == units.length) { 146 return MixedRadix.of(units).createQuantity(values, scale); 147 } else { 148 throw new IllegalArgumentException( 149 String.format("%s values don't match %s units", values.length, units.length)); 150 } 151 } 152 153 /** 154 * Returns the mixed radix values and units combined into a single quantity in 155 * the {@code ABSOLUTE} scale. 156 * 157 * @param values the measurement values. 158 * @param units the measurement units. 159 * @return the corresponding quantity. 160 * @throws NullPointerException if values or units were null 161 * @throws IllegalArgumentException if the size of the values array does not 162 * match that of units. 163 * @since 2.0 164 */ 165 @SafeVarargs 166 public static <Q extends Quantity<Q>> Quantity<Q> getQuantity(Number[] values, Unit<Q>... units) { 167 return getQuantity(values, units, ABSOLUTE); 168 } 169 170 /** 171 * Returns the mixed radix values and units as {@link MixedQuantity} in the 172 * specified scale. 173 * 174 * @param values the measurement values. 175 * @param units the measurement units. 176 * @param scale the measurement scale. 177 * @return the corresponding mixed quantity. 178 * @throws NullPointerException if values, units or scale were null 179 * @throws IllegalArgumentException if the size of the values array does not 180 * match that of units. 181 * @since 2.1.2 182 */ 183 public static <Q extends Quantity<Q>> MixedQuantity<Q> getMixedQuantity(Number[] values, Unit<Q>[] units, 184 Scale scale) { 185 Objects.requireNonNull(values); 186 Objects.requireNonNull(units); 187 if (values.length == units.length) { 188 return MixedRadix.of(units).createMixedQuantity(values, scale); 189 } else { 190 throw new IllegalArgumentException( 191 String.format("%s values don't match %s units", values.length, units.length)); 192 } 193 } 194 195 /** 196 * Returns the mixed radix values and units as {@link MixedQuantity} in the 197 * {@code ABSOLUTE} scale. 198 * 199 * @param values the measurement values. 200 * @param units the measurement units. 201 * @return the corresponding mixed quantity. 202 * @throws NullPointerException if values, units or scale were null 203 * @throws IllegalArgumentException if the size of the values array does not 204 * match that of units. 205 * @since 2.1.2 206 */ 207 public static <Q extends Quantity<Q>> MixedQuantity<Q> getMixedQuantity(final Number[] values, 208 final Unit<Q>[] units) { 209 return getMixedQuantity(values, units, ABSOLUTE); 210 } 211}