001/* 002 * Units of Measurement Implementation for Java SE 003 * Copyright (c) 2005-2017, Jean-Marie Dautelle, Werner Keil, V2COM. 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-363 nor the names of its 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 tec.uom.se.quantity; 031 032import java.io.Serializable; 033import java.math.BigDecimal; 034import java.math.BigInteger; 035import java.math.MathContext; 036 037import javax.measure.Quantity; 038import javax.measure.UnconvertibleException; 039import javax.measure.Unit; 040import javax.measure.UnitConverter; 041 042import tec.uom.se.AbstractQuantity; 043import tec.uom.se.ComparableQuantity; 044 045/** 046 * An amount of quantity, implementation of {@link ComparableQuantity} that keep {@link Number} as possible otherwise converts to 047 * {@link DecimalQuantity}, this object is immutable. 048 * 049 * @see AbstractQuantity 050 * @see Quantity 051 * @see ComparableQuantity 052 * @param <Q> 053 * The type of the quantity. 054 * @author otaviojava 055 * @author <a href="mailto:units@catmedia.us">Werner Keil</a> 056 * @version 1.0, $Date: 2016-10-02 $ 057 */ 058@SuppressWarnings({ "rawtypes", "unchecked" }) 059public class NumberQuantity<Q extends Quantity<Q>> extends AbstractQuantity<Q> implements Serializable { 060 061 private static final long serialVersionUID = 7312161895652321241L; 062 063 private final Number value; 064 065 /** 066 * Indicates if this quantity is big. 067 */ 068 private final boolean isBig; 069 070 protected NumberQuantity(Number number, Unit<Q> unit) { 071 super(unit); 072 value = number; 073 isBig = number instanceof BigDecimal || number instanceof BigInteger; 074 } 075 076 @Override 077 public double doubleValue(Unit<Q> unit) { 078 Unit<Q> myUnit = getUnit(); 079 try { 080 UnitConverter converter = myUnit.getConverterTo(unit); 081 return converter.convert(getValue().doubleValue()); 082 } catch (UnconvertibleException e) { 083 throw e; 084 } 085 } 086 087 @Override 088 public Number getValue() { 089 return value; 090 } 091 092 /** 093 * Indicates if this measured amount is a big number, i.E. BigDecimal or BigInteger. In all other cases this would be false. 094 * 095 * @return <code>true</code> if this quantity is big; <code>false</code> otherwise. 096 */ 097 @Override 098 public boolean isBig() { 099 return isBig; 100 } 101 102 @Override 103 public ComparableQuantity<Q> add(Quantity<Q> that) { 104 return toDecimalQuantity().add(that); 105 } 106 107 @Override 108 public ComparableQuantity<?> multiply(Quantity<?> that) { 109 return toDecimalQuantity().multiply(that); 110 } 111 112 @Override 113 public ComparableQuantity<Q> multiply(Number that) { 114 return toDecimalQuantity().multiply(that); 115 } 116 117 @Override 118 public ComparableQuantity<?> divide(Quantity<?> that) { 119 return toDecimalQuantity().divide(that); 120 } 121 122 @Override 123 public ComparableQuantity<Q> divide(Number that) { 124 return toDecimalQuantity().divide(that); 125 } 126 127 @Override 128 public ComparableQuantity<Q> inverse() { 129 130 return new NumberQuantity((getValue() instanceof BigDecimal ? BigDecimal.ONE.divide((BigDecimal) getValue()) : 1d / getValue().doubleValue()), 131 getUnit().inverse()); 132 } 133 134 @Override 135 public BigDecimal decimalValue(Unit<Q> unit, MathContext ctx) throws ArithmeticException { 136 if (value instanceof BigDecimal) { 137 return (BigDecimal) value; 138 } 139 if (value instanceof BigInteger) { 140 return new BigDecimal((BigInteger) value); 141 } 142 return BigDecimal.valueOf(value.doubleValue()); 143 } 144 145 @Override 146 public ComparableQuantity<Q> subtract(Quantity<Q> that) { 147 return toDecimalQuantity().subtract(that); 148 } 149 150 private DecimalQuantity<Q> toDecimalQuantity() { 151 return new DecimalQuantity<>(BigDecimal.valueOf(value.doubleValue()), getUnit()); 152 } 153 154 /** 155 * Returns the scalar quantity for the specified <code>double</code> stated in the specified unit. 156 * 157 * @param doubleValue 158 * the measurement value. 159 * @param unit 160 * the measurement unit. 161 * @return the corresponding <code>double</code> quantity. 162 */ 163 public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(double doubleValue, Unit<Q> unit) { 164 return new DoubleQuantity<Q>(doubleValue, unit); 165 } 166}