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