View Javadoc
1   /*
2    * Copyright (C) 2018 Alberto Irurueta Carro (alberto@irurueta.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.irurueta.units;
18  
19  import java.io.Serializable;
20  
21  /**
22   * Base class to define a measurement unit and value.
23   *
24   * @param <T> a measurement unit.
25   */
26  public abstract class Measurement<T extends Enum<?>> implements Serializable {
27  
28      /**
29       * Measurement value.
30       */
31      private Number value;
32  
33      /**
34       * Measurement unit.
35       */
36      private T unit;
37  
38      /**
39       * Constructor.
40       *
41       * @param value measurement value.
42       * @param unit  measurement unit.
43       * @throws IllegalArgumentException if either value or unit is null.
44       */
45      protected Measurement(final Number value, final T unit) {
46          if (value == null || unit == null) {
47              throw new IllegalArgumentException();
48          }
49  
50          this.value = value;
51          this.unit = unit;
52      }
53  
54      /**
55       * Constructor.
56       */
57      Measurement() {
58      }
59  
60      /**
61       * Determines if two measurements are equal.
62       *
63       * @param obj another object to compare.
64       * @return true if provided object is assumed to be equal to this instance, false otherwise.
65       */
66      @Override
67      public boolean equals(final Object obj) {
68          if (obj == null) {
69              return false;
70          }
71          if (!(obj instanceof Measurement)) {
72              return false;
73          }
74          if (this == obj) {
75              return true;
76          }
77  
78          //noinspection unchecked
79          final var other = (Measurement<T>) obj;
80          return value != null && unit != null &&
81                  other.value != null && other.unit != null &&
82                  value.equals(other.value) && unit == other.unit;
83      }
84  
85      /**
86       * Hash code generated for this instance. Hash codes can be internally used by some collections to coarsely
87       * compare objects.
88       *
89       * @return hash code.
90       */
91      @Override
92      public int hashCode() {
93          var hash = 7;
94          hash = 19 * hash + (value != null ? value.hashCode() : 0);
95          hash = 19 * hash + (unit != null ? unit.hashCode() : 0);
96          return hash;
97      }
98  
99      /**
100      * Determines if two measurements are equal up to a certain tolerance.
101      *
102      * @param other     another measurement to compare.
103      * @param tolerance amount of tolerance to determine whether two measurements are equal or not.
104      * @return true if provided measurement is assumed to be equal to this instance, false otherwise.
105      */
106     public boolean equals(final Measurement<T> other, final double tolerance) {
107         return value != null && unit != null && other != null &&
108                 other.value != null && other.unit != null &&
109                 unit == other.unit &&
110                 (Math.abs(value.doubleValue() - other.value.doubleValue()) <= tolerance);
111     }
112 
113     /**
114      * Returns measurement value.
115      *
116      * @return measurement value.
117      */
118     public Number getValue() {
119         return value;
120     }
121 
122     /**
123      * Sets measurement value.
124      *
125      * @param value measurement value.
126      * @throws IllegalArgumentException if measurement value is null.
127      */
128     public void setValue(final Number value) {
129         if (value == null) {
130             throw new IllegalArgumentException();
131         }
132 
133         this.value = value;
134     }
135 
136     /**
137      * Returns measurement unit.
138      *
139      * @return measurement unit.
140      */
141     public T getUnit() {
142         return unit;
143     }
144 
145     /**
146      * Sets measurement unit.
147      *
148      * @param unit measurement unit.
149      * @throws IllegalArgumentException if measurement unit is null.
150      */
151     public void setUnit(final T unit) {
152         if (unit == null) {
153             throw new IllegalArgumentException();
154         }
155 
156         this.unit = unit;
157     }
158 }