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