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.time;
031
032import static tec.uom.se.unit.Units.DAY;
033import static tec.uom.se.unit.Units.HOUR;
034import static tec.uom.se.unit.Units.MINUTE;
035import static tec.uom.se.unit.Units.SECOND;
036
037import java.math.BigDecimal;
038import java.math.MathContext;
039import java.util.Objects;
040import java.util.concurrent.TimeUnit;
041
042import javax.measure.IncommensurableException;
043import javax.measure.Quantity;
044import javax.measure.UnconvertibleException;
045import javax.measure.Unit;
046import javax.measure.UnitConverter;
047import javax.measure.quantity.Time;
048
049import tec.uom.se.AbstractQuantity;
050import tec.uom.se.ComparableQuantity;
051import tec.uom.se.quantity.Quantities;
052
053/**
054 * Class that represents {@link TimeUnit} in Unit-API
055 * 
056 * @author otaviojava
057 * @author keilw
058 * @since 1.0
059 */
060public final class TimeUnitQuantity extends AbstractQuantity<Time> {
061
062  /**
063         * 
064         */
065  private static final long serialVersionUID = -5840251813363744230L;
066
067  private final TimeUnit timeUnit;
068
069  private final Integer value;
070
071  /**
072   * creates the {@link TimeUnitQuantity} using {@link TimeUnit} and {@link Integer}
073   * 
074   * @param timeUnit
075   *          - time to be used
076   * @param value
077   *          - value to be used
078   */
079  TimeUnitQuantity(TimeUnit timeUnit, Integer value) {
080    super(toUnit(timeUnit));
081    this.timeUnit = timeUnit;
082    this.value = value;
083  }
084
085  /**
086   * creates the {@link TimeUnitQuantity} using {@link TimeUnit} and {@link Integer}
087   * 
088   * @param timeUnit
089   *          - time to be used
090   * @param value
091   *          - value to be used
092   * @since 1.0
093   */
094  public static TimeUnitQuantity of(TimeUnit timeUnit, Integer number) {
095    return new TimeUnitQuantity(Objects.requireNonNull(timeUnit), Objects.requireNonNull(number));
096  }
097
098  /**
099   * Creates a {@link TimeUnitQuantity} based a {@link Quantity<Time>} converted to {@link SI#SECOND}.
100   * 
101   * @param quantity
102   *          - quantity to be used
103   * @return the {@link TimeUnitQuantity} converted be quantity in seconds.
104   * @since 1.0
105   */
106  public static TimeUnitQuantity of(Quantity<Time> quantity) {
107    Quantity<Time> seconds = Objects.requireNonNull(quantity).to(SECOND);
108    return new TimeUnitQuantity(TimeUnit.SECONDS, seconds.getValue().intValue());
109  }
110
111  /**
112   * get to {@link TimeUnit}
113   * 
114   * @return the TimeUnit
115   * @since 1.0
116   */
117  public TimeUnit getTimeUnit() {
118    return timeUnit;
119  }
120
121  /**
122   * get value expressed in {@link Integer}
123   * 
124   * @return the value
125   * @since 1.0
126   */
127  public Integer getValue() {
128    return value;
129  }
130
131  /**
132   * converts the {@link TimeUnit} to {@link Unit}
133   * 
134   * @return the {@link TimeUnitQuantity#getTimeUnit()} converted to Unit
135   * @since 1.0
136   */
137  public Unit<Time> toUnit() {
138    return toUnit(timeUnit);
139  }
140
141  /**
142   * Converts the {@link TimeUnitQuantity} to {@link Quantity<Time>}
143   * 
144   * @return this class converted to Quantity
145   * @since 1.0
146   */
147  public Quantity<Time> toQuantity() {
148    return Quantities.getQuantity(value, toUnit());
149  }
150
151  public TimeUnitQuantity to(TimeUnit timeUnit) {
152    Quantity<Time> time = toQuantity().to(toUnit(timeUnit));
153    return new TimeUnitQuantity(timeUnit, time.getValue().intValue());
154  }
155
156  private static Unit<Time> toUnit(TimeUnit timeUnit) {
157    switch (timeUnit) {
158      case MICROSECONDS:
159        return TimeQuantities.MICROSECOND;
160      case MILLISECONDS:
161        return TimeQuantities.MILLISECOND;
162      case NANOSECONDS:
163        return TimeQuantities.NANOSECOND;
164      case SECONDS:
165        return SECOND;
166      case MINUTES:
167        return MINUTE;
168      case HOURS:
169        return HOUR;
170      case DAYS:
171        return DAY;
172      default:
173        throw new IllegalStateException("In TimeUnitQuantity just supports DAYS, HOURS, MICROSECONDS, MILLISECONDS, MINUTES, NANOSECONDS, SECONDS ");
174    }
175  }
176
177  /**
178   * @since 1.0
179   */
180  @Override
181  public int hashCode() {
182    return Objects.hash(timeUnit, value);
183  }
184
185  /**
186   * @since 1.0
187   */
188  @Override
189  public boolean equals(Object obj) {
190    if (this == obj) {
191      return true;
192    }
193    if (TimeUnitQuantity.class.isInstance(obj)) {
194      TimeUnitQuantity other = TimeUnitQuantity.class.cast(obj);
195      return Objects.equals(timeUnit, other.timeUnit) && Objects.equals(value, other.value);
196    }
197    return super.equals(obj);
198  }
199
200  @Override
201  public String toString() {
202    return "Time unit:" + timeUnit + " value: " + value;
203  }
204
205  /**
206   * @since 1.0.1
207   */
208  @Override
209  public ComparableQuantity<Time> add(Quantity<Time> that) {
210    if (getUnit().equals(that.getUnit())) {
211      return TimeQuantities.getQuantity(value + that.getValue().intValue(), timeUnit);
212    }
213    Quantity<Time> converted = that.to(getUnit());
214    return TimeQuantities.getQuantity(value + converted.getValue().intValue(), timeUnit);
215  }
216
217  /**
218   * @since 1.0.1
219   */
220  @Override
221  public ComparableQuantity<Time> subtract(Quantity<Time> that) {
222    if (getUnit().equals(that.getUnit())) {
223      return TimeQuantities.getQuantity(value - that.getValue().intValue(), timeUnit);
224    }
225    Quantity<Time> converted = that.to(getUnit());
226    return TimeQuantities.getQuantity(value - converted.getValue().intValue(), timeUnit);
227  }
228
229  /**
230   * @since 1.0.1
231   */
232  @Override
233  public ComparableQuantity<?> divide(Quantity<?> that) {
234    if (getUnit().equals(that.getUnit())) {
235      return TimeQuantities.getQuantity(value / that.getValue().intValue(), timeUnit);
236    }
237    Unit<?> divUnit = getUnit().divide(that.getUnit());
238    UnitConverter conv;
239    try {
240      conv = getUnit().getConverterToAny(divUnit);
241      return TimeQuantities.getQuantity(value / conv.convert(that.getValue()).intValue(), timeUnit);
242    } catch (UnconvertibleException e) {
243      // TODO Auto-generated catch block
244      e.printStackTrace();
245      return TimeQuantities.getQuantity(value / that.getValue().intValue(), timeUnit);
246    } catch (IncommensurableException e) {
247      // TODO Auto-generated catch block
248      e.printStackTrace();
249      return TimeQuantities.getQuantity(value / that.getValue().intValue(), timeUnit);
250    }
251  }
252
253  /**
254   * @since 1.0.1
255   */
256  @Override
257  public ComparableQuantity<Time> divide(Number that) {
258    return TimeQuantities.getQuantity(value / that.intValue(), timeUnit);
259  }
260
261  /**
262   * @since 1.0.1
263   */
264  @Override
265  public ComparableQuantity<?> multiply(Quantity<?> multiplier) {
266    if (getUnit().equals(multiplier.getUnit())) {
267      return TimeQuantities.getQuantity(value * multiplier.getValue().intValue(), timeUnit);
268    }
269    Unit<?> mulUnit = getUnit().multiply(multiplier.getUnit());
270    UnitConverter conv;
271    try {
272      conv = getUnit().getConverterToAny(mulUnit);
273      return TimeQuantities.getQuantity(value * conv.convert(multiplier.getValue()).intValue(), timeUnit);
274    } catch (UnconvertibleException e) {
275      // TODO Auto-generated catch block
276      e.printStackTrace();
277      return TimeQuantities.getQuantity(value * multiplier.getValue().intValue(), timeUnit);
278    } catch (IncommensurableException e) {
279      // TODO Auto-generated catch block
280      e.printStackTrace();
281      return TimeQuantities.getQuantity(value * multiplier.getValue().intValue(), timeUnit);
282    }
283  }
284
285  /**
286   * @since 1.0.1
287   */
288  @Override
289  public ComparableQuantity<Time> multiply(Number multiplier) {
290    return TimeQuantities.getQuantity(value * multiplier.intValue(), timeUnit);
291  }
292
293  /**
294   * @since 1.0.1
295   */
296  @Override
297  public ComparableQuantity<?> inverse() {
298    return TimeQuantities.getQuantity(1 / value, timeUnit);
299  }
300
301  /**
302   * @since 1.0.1
303   */
304  @Override
305  public boolean isBig() {
306    return false;
307  }
308
309  /**
310   * @since 1.0.1
311   */
312  @Override
313  public BigDecimal decimalValue(Unit<Time> unit, MathContext ctx) throws ArithmeticException {
314    return BigDecimal.valueOf(value.doubleValue());
315  }
316
317  /**
318   * @since 1.0.1
319   */
320  @Override
321  public double doubleValue(Unit<Time> unit) throws ArithmeticException {
322    return value.doubleValue();
323  }
324}