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.unit;
031
032import javax.measure.Dimension;
033import javax.measure.Quantity;
034import javax.measure.Unit;
035import javax.measure.UnitConverter;
036
037import tech.units.indriya.AbstractUnit;
038
039import java.util.Map;
040import java.util.Objects;
041
042/**
043 * <p>
044 * This class represents units used in expressions to distinguish between quantities of a different nature but of the same dimensions.
045 * </p>
046 *
047 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
048 * @author <a href="mailto:units@catmedia.us">Werner Keil</a>
049 * @version 1.3.1, August 06, 2017
050 * @since 1.0
051 */
052public final class AlternateUnit<Q extends Quantity<Q>> extends AbstractUnit<Q> {
053
054  /**
055     * 
056     */
057  private static final long serialVersionUID = 4696690756456282705L;
058
059  /**
060   * Holds the parent unit (a system unit).
061   */
062  private final Unit<?> parentUnit;
063
064  /**
065   * Holds the symbol for this unit.
066   */
067  private final String symbol;
068
069  /**
070   * Creates an alternate unit for the specified system unit identified by the specified name and symbol.
071   *
072   * @param parent
073   *          the system unit from which this alternate unit is derived.
074   * @param symbol
075   *          the symbol for this alternate unit.
076   * @throws IllegalArgumentException
077   *           if the specified parent unit is not an {@link AbstractUnit#isSystemUnit() system unit}
078   */
079  public AlternateUnit(Unit<?> parentUnit, String symbol) {
080    if (!((AbstractUnit) parentUnit).isSystemUnit())
081      throw new IllegalArgumentException("The parent unit: " + parentUnit + " is not an unscaled SI unit");
082    this.parentUnit = (parentUnit instanceof AlternateUnit) ? ((AlternateUnit) parentUnit).getParentUnit() : parentUnit;
083    this.symbol = symbol;
084  }
085
086  /**
087   * Returns the parent unit of this alternate unit, always a system unit and never an alternate unit.
088   *
089   * @return the parent unit.
090   */
091  public Unit<?> getParentUnit() {
092    return parentUnit;
093  }
094
095  @Override
096  public String getSymbol() {
097    return symbol;
098  }
099
100  @Override
101  public Dimension getDimension() {
102    return parentUnit.getDimension();
103  }
104
105  @Override
106  public UnitConverter getSystemConverter() {
107    return ((AbstractUnit) parentUnit).getSystemConverter();
108  }
109
110  @Override
111  public Unit<Q> toSystemUnit() {
112    return this; // Alternate units are SI units.
113  }
114
115  @Override
116  public Map<? extends Unit<?>, Integer> getBaseUnits() {
117    return parentUnit.getBaseUnits();
118  }
119
120  @Override
121  public int hashCode() {
122    return Objects.hashCode(symbol);
123  }
124
125  @SuppressWarnings("rawtypes")
126  @Override
127  public boolean equals(Object obj) {
128    if (this == obj) {
129      return true;
130    }
131    if (obj instanceof AlternateUnit) {
132      AlternateUnit that = (AlternateUnit) obj;
133      return Objects.equals(parentUnit, that.parentUnit) && Objects.equals(symbol, that.symbol);
134    }
135    if (obj instanceof AbstractUnit) {
136      return AbstractUnit.Equalizer.areEqual(this, (AbstractUnit) obj);
137    } else {
138      return false;
139    }
140  }
141}