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.spi;
031
032import java.util.Objects;
033
034import tec.uom.lib.common.function.MaximumSupplier;
035import tec.uom.lib.common.function.MinimumSupplier;
036
037/**
038 * A Measurement Range is a pair of <code>T</code> items that represent a range of values.
039 * <p>
040 * Range limits MUST be presented in the same scale and have the same unit as measured data values.<br/>
041 * Subclasses of Range should be immutable.
042 * 
043 * @param <T>
044 *          The value of the range.
045 * 
046 * @author <a href="mailto:units@catmedia.us">Werner Keil</a>
047 * @version 0.8.9, December 28, 2015
048 * @see <a href="http://www.botts-inc.com/SensorML_1.0.1/schemaBrowser/SensorML_QuantityRange.html"> SensorML: QuantityRange</a>
049 */
050public abstract class Range<T> implements MinimumSupplier<T>, MaximumSupplier<T> {
051  // TODO do we keep null for min and max to represent infinity?
052  // Java 8 Optional was evaluated, but caused conflict with the type-safe
053  // Quantity feature of this API, plus it won't work in CLDC8
054  private final T min;
055  private final T max;
056  private T res;
057
058  /**
059   * Construct an instance of Range with a min, max and res value.
060   *
061   * @param min
062   *          The minimum value for the measurement range.
063   * @param max
064   *          The maximum value for the measurement range.
065   * @param res
066   *          The resolution of the measurement range.
067   */
068  protected Range(T min, T max, T res) {
069    this.min = min;
070    this.max = max;
071    this.res = res;
072  }
073
074  /**
075   * Construct an instance of Range with a min and max value.
076   *
077   * @param min
078   *          The minimum value for the measurement range.
079   * @param max
080   *          The maximum value for the measurement range.
081   */
082  protected Range(T min, T max) {
083    this.min = min;
084    this.max = max;
085  }
086
087  /**
088   * Returns the smallest value of the range. The value is the same as that given as the constructor parameter for the smallest value.
089   * 
090   * @return the minimum value
091   */
092  public T getMinimum() {
093    return min;
094  }
095
096  /**
097   * Returns the largest value of the measurement range. The value is the same as that given as the constructor parameter for the largest value.
098   * 
099   * @return the maximum value
100   */
101  public T getMaximum() {
102    return max;
103  }
104
105  /**
106   * Returns the resolution of the measurement range. The value is the same as that given as the constructor parameter for the largest value.
107   * 
108   * @return resolution of the range, the value is the same as that given as the constructor parameter for the resolution
109   */
110  public T getResolution() {
111    return res;
112  }
113
114  /**
115   * Method to easily check if {@link #getMinimum()} is not {@code null}.
116   * 
117   * @return {@code true} if {@link #getMinimum()} is not {@code null} .
118   */
119  public boolean hasMinimum() {
120    return min != null;
121  }
122
123  /**
124   * Method to easily check if {@link #getMaximum()} is not {@code null}.
125   * 
126   * @return {@code true} if {@link #getMaximum()} is not {@code null}.
127   */
128  public boolean hasMaximum() {
129    return max != null;
130  }
131
132  /**
133   * Checks whether the given <code>T</code> is within this range
134   * 
135   * @param t
136   * @return true if the value is within the range
137   */
138  public abstract boolean contains(T t);
139
140  /*
141   * (non-Javadoc)
142   * 
143   * @see java.lang.Object#equals()
144   */
145  @Override
146  public boolean equals(Object obj) {
147    if (this == obj) {
148      return true;
149    }
150    if (obj instanceof Range<?>) {
151      @SuppressWarnings("unchecked")
152      final Range<T> other = (Range<T>) obj;
153      return Objects.equals(getMinimum(), other.getMinimum()) && Objects.equals(getMaximum(), other.getMaximum())
154          && Objects.equals(getResolution(), other.getResolution());
155    }
156    return false;
157  }
158
159  /*
160   * (non-Javadoc)
161   * 
162   * @see java.lang.Object#hashCode()
163   */
164  @Override
165  public int hashCode() {
166    return Objects.hash(min, max, res);
167  }
168
169  /*
170   * (non-Javadoc)
171   * 
172   * @see java.lang.Object#toString()
173   */
174  @Override
175  public String toString() {
176    final StringBuilder sb = new StringBuilder().append("min= ").append(getMinimum()).append(", max= ").append(getMaximum());
177    if (res != null) {
178      sb.append(", res= ").append(getResolution());
179    }
180    return sb.toString();
181  }
182}