001/*
002 * Units of Measurement Reference Implementation
003 * Copyright (c) 2005-2016, 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.units.ri;
031
032import java.util.HashMap;
033import java.util.HashSet;
034import java.util.Map;
035import java.util.Set;
036import java.util.logging.Level;
037import java.util.logging.Logger;
038
039import javax.measure.Dimension;
040import javax.measure.Quantity;
041import javax.measure.Unit;
042import javax.measure.spi.SystemOfUnits;
043
044/**
045 * <p>
046 * An abstract base class for unit systems.
047 * </p>
048 *
049 * @author <a href="mailto:units@catmedia.us">Werner Keil</a>
050 * @version 1.0, August 9, 2016
051 */
052public abstract class AbstractSystemOfUnits implements SystemOfUnits {
053  protected static final Logger logger = Logger.getLogger(AbstractSystemOfUnits.class.getName());
054
055  /**
056   * Holds the units.
057   */
058  protected final Set<Unit<?>> units = new HashSet<Unit<?>>();
059
060  /**
061   * Holds the mapping quantity to unit.
062   */
063  @SuppressWarnings("rawtypes")
064  protected final Map<Class<? extends Quantity>, Unit> quantityToUnit = new HashMap<Class<? extends Quantity>, Unit>();
065
066  /**
067   * The natural logarithm.
068   **/
069  protected static final double E = 2.71828182845904523536028747135266;
070
071  /*
072   * (non-Javadoc)
073   * 
074   * @see SystemOfUnits#getName()
075   */
076  public abstract String getName();
077
078  // ///////////////////
079  // Collection View //
080  // ///////////////////
081  public Set<Unit<?>> getUnits() {
082    if (logger.isLoggable(Level.FINEST)) {
083      for (Unit<?> u : units) {
084        logger.log(Level.FINEST, u + "; D: " + u.getDimension() + "; C: " + u.getClass());
085      }
086    }
087    return units;
088  }
089
090  @Override
091  public Set<? extends Unit<?>> getUnits(Dimension dimension) {
092    final Set<Unit<?>> set = new HashSet<Unit<?>>();
093    for (Unit<?> unit : this.getUnits()) {
094      if (dimension.equals(unit.getDimension())) {
095        set.add(unit);
096      }
097    }
098    return set;
099  }
100
101  @SuppressWarnings("unchecked")
102  public <Q extends Quantity<Q>> Unit<Q> getUnit(Class<Q> quantityType) {
103    return quantityToUnit.get(quantityType);
104  }
105
106  /**
107   * Adds a new named unit to the collection.
108   * 
109   * @param unit
110   *          the unit being added.
111   * @param name
112   *          the name of the unit.
113   * @param name
114   *          the symbol of the unit.
115   * @return <code>unit</code>.
116   */
117  @SuppressWarnings("unchecked")
118  protected <U extends Unit<?>> U addUnit(U unit, String name, String symbol) {
119    if (name != null && symbol != null && unit instanceof AbstractUnit) {
120      AbstractUnit<?> aUnit = (AbstractUnit<?>) unit;
121      aUnit.setName(name);
122      aUnit.setSymbol(symbol);
123      units.add(aUnit);
124      return (U) aUnit;
125    }
126    if (name != null && unit instanceof AbstractUnit) {
127      AbstractUnit<?> aUnit = (AbstractUnit<?>) unit;
128      aUnit.setName(name);
129      units.add(aUnit);
130      return (U) aUnit;
131    }
132    units.add(unit);
133    return unit;
134  }
135
136  /**
137   * Adds a new named unit to the collection.
138   * 
139   * @param unit
140   *          the unit being added.
141   * @param name
142   *          the name of the unit.
143   * @return <code>unit</code>.
144   */
145  @SuppressWarnings("unchecked")
146  protected <U extends Unit<?>> U addUnit(U unit, String name) {
147    if (name != null && unit instanceof AbstractUnit) {
148      AbstractUnit<?> aUnit = (AbstractUnit<?>) unit;
149      aUnit.setName(name);
150      units.add(aUnit);
151      return (U) aUnit;
152    }
153    units.add(unit);
154    return unit;
155  }
156
157  protected static class Helper {
158    static Set<Unit<?>> getUnitsOfDimension(final Set<Unit<?>> units, Dimension dimension) {
159      if (dimension != null) {
160        Set<Unit<?>> dimSet = new HashSet<Unit<?>>();
161        for (Unit<?> u : units) {
162          if (dimension.equals(u.getDimension())) {
163            dimSet.add(u);
164          }
165        }
166        return dimSet;
167      }
168      return null;
169    }
170
171    /**
172     * Adds a new named unit to the collection.
173     * 
174     * @param unit
175     *          the unit being added.
176     * @param name
177     *          the name of the unit.
178     * @return <code>unit</code>.
179     */
180    @SuppressWarnings("unchecked")
181    public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String name) {
182      if (name != null && unit instanceof AbstractUnit) {
183        AbstractUnit<?> aUnit = (AbstractUnit<?>) unit;
184        aUnit.setName(name);
185        units.add(aUnit);
186        return (U) aUnit;
187      }
188      units.add(unit);
189      return unit;
190    }
191
192    /**
193     * Adds a new named unit to the collection.
194     * 
195     * @param unit
196     *          the unit being added.
197     * @param name
198     *          the name of the unit.
199     * @param name
200     *          the symbol of the unit.
201     * @return <code>unit</code>.
202     */
203    @SuppressWarnings("unchecked")
204    public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String name, String symbol) {
205      if (name != null && symbol != null && unit instanceof AbstractUnit) {
206        AbstractUnit<?> aUnit = (AbstractUnit<?>) unit;
207        aUnit.setName(name);
208        aUnit.setSymbol(symbol);
209        units.add(aUnit);
210        return (U) aUnit;
211      }
212      if (name != null && unit instanceof AbstractUnit) {
213        AbstractUnit<?> aUnit = (AbstractUnit<?>) unit;
214        aUnit.setName(name);
215        units.add(aUnit);
216        return (U) aUnit;
217      }
218      units.add(unit);
219      return unit;
220    }
221  }
222}