001/*
002 * Units of Measurement Systems
003 * Copyright (c) 2005-2019, Jean-Marie Dautelle, Werner Keil and others.
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, Units of Measurement nor the names of their contributors may be used to
017 *    endorse or promote products 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 systems.uom.common;
031
032import static tech.units.indriya.AbstractUnit.ONE;
033import static tech.units.indriya.unit.MetricPrefix.CENTI;
034import static tech.units.indriya.unit.Units.JOULE;
035import static tech.units.indriya.unit.Units.METRE;
036import static tech.units.indriya.unit.Units.NEWTON;
037import static tech.units.indriya.unit.Units.PASCAL;
038
039import java.util.Objects;
040
041import javax.measure.Unit;
042import javax.measure.quantity.Acceleration;
043import javax.measure.quantity.Energy;
044import javax.measure.quantity.Force;
045import javax.measure.quantity.Length;
046import javax.measure.quantity.Mass;
047import javax.measure.quantity.Power;
048import javax.measure.quantity.Pressure;
049import javax.measure.quantity.Speed;
050import javax.measure.quantity.Time;
051
052import si.uom.quantity.DynamicViscosity;
053import si.uom.quantity.KinematicViscosity;
054import tech.units.indriya.AbstractSystemOfUnits;
055import tech.units.indriya.AbstractUnit;
056import tech.units.indriya.format.SimpleUnitFormat;
057import tech.units.indriya.unit.ProductUnit;
058import tech.units.indriya.unit.Units;
059
060/**
061 * <p>
062 * This class contains the centimetre–gram–second system of units.
063 * </p>
064 * 
065 * <p>
066 * This class is not intended to be implemented by clients.
067 * </p>
068 * 
069 * @noextend This class is not intended to be extended by clients.
070 * 
071 * @author <a href="mailto:units@catmedia.us">Werner Keil</a>
072 * @version 0.6, $Date: 2019-01-21$
073 * @see <a href= "https://en.wikipedia.org/wiki/Centimetre%E2%80%93gram%E2%80%93second_system_of_units">Wikipedia: Centimetre–gram–second system of
074 *      units</a>
075 * @since 0.6
076 */
077public final class CGS extends AbstractSystemOfUnits {
078    private static final String SYSTEM_NAME = "Centimetre–gram–second System of Units";
079
080    /**
081     * Holds the avoirdupois pound: 0.45359237 kg exact
082     */
083    static final int AVOIRDUPOIS_POUND_DIVIDEND = 45359237;
084
085    static final int AVOIRDUPOIS_POUND_DIVISOR = 100000000;
086
087    /**
088     * Default constructor (prevents this class from being instantiated).
089     */
090    private CGS() {
091    }
092
093    /**
094     * Returns the unique instance of this class.
095     * 
096     * @return the NonSI instance.
097     */
098    public static CGS getInstance() {
099        return INSTANCE;
100    }
101
102    private static final CGS INSTANCE = new CGS();
103
104    ////////////
105    // Length //
106    ////////////
107
108    /**
109     * A unit of length equal to <code>1/100 of metre</code> (standard name <code>cm</code>).
110     */
111    public static final Unit<Length> CENTIMETRE = addUnit(CENTI(METRE));
112
113    //////////
114    // Mass //
115    //////////
116    /**
117     * A unit of mass equal to 1/12 the mass of the carbon-12 atom (standard name <code>g</code>).
118     */
119    public static final Unit<Mass> GRAM = addUnit(Units.GRAM);
120
121    //////////
122    // Time //
123    //////////
124    /**
125     * The SI base unit for duration quantities (standard name <code>s</code>). It is defined as the duration of 9,192,631,770 cycles of radiation
126     * corresponding to the transition between two hyperfine levels of the ground state of cesium (1967 Standard).
127     * 
128     */
129    public static final Unit<Time> SECOND = addUnit(Units.SECOND);
130
131    //////////////
132    // Velocity //
133    //////////////
134    /**
135     * A unit of velocity (cgs unit, standard name <code>cm/s</code>.
136     */
137    public static final Unit<Speed> CENTIMETRE_PER_SECOND = addUnit(CENTIMETRE.divide(SECOND).asType(Speed.class), "centimetre per second", "cm/s");
138
139    //////////////////
140    // Acceleration //
141    //////////////////
142
143    /**
144     * A unit of acceleration (cgs unit, standard name <code>Gal</code>).
145     * 
146     * @see <a href="https://en.wikipedia.org/wiki/Gal_(unit)">Wikipedia: Gal</a>
147     */
148    public static final Unit<Acceleration> GAL = addUnit(
149            new ProductUnit<Acceleration>(CENTIMETRE_PER_SECOND.divide(SECOND)).asType(Acceleration.class), "Gal", "Gal");
150
151    ////////////
152    // Energy //
153    ////////////
154    /**
155     * A unit of energy equal to <code>1E-7 J</code> (standard name <code>erg</code>).
156     */
157    public static final Unit<Energy> ERG = addUnit(JOULE.divide(10000000), "Erg", "erg");
158
159    ///////////
160    // Force //
161    ///////////
162    /**
163     * A unit of force equal to <code>1E-5 N</code> (standard name <code>dyn</code>).
164     */
165    public static final Unit<Force> DYNE = addUnit(NEWTON.divide(100000), "Dyne", "dyn");
166
167    ///////////
168    // Power //
169    ///////////
170
171    /**
172     * A unit of power (cgs unit, standard name <code>erg/s</code>).
173     */
174    public static final Unit<Power> ERG_PER_SECOND = addUnit(ERG.divide(SECOND).asType(Power.class), "Erg per second", "erg/s");
175
176    //////////////
177    // Pressure //
178    //////////////
179
180    /**
181     * The barye (symbol: <code>Ba</code>), or sometimes barad, barrie, bary, baryd, baryed, or barie, is the centimetre–gram–second (CGS) unit of
182     * pressure. It is equal to 1 dyne per square centimetre.
183     * <p>
184     * <code>1 Ba = 0.1 Pa = 1×10−6 bar = 1×10−4 pieze = 0.1 N/m2 = 1 g⋅cm−1⋅s−2</code>
185     */
186    public static final Unit<Pressure> BARYE = addUnit(PASCAL.divide(10), "Barye", "Ba");
187
188    ///////////////
189    // Viscosity //
190    ///////////////
191
192    /**
193     * A unit of dynamic viscosity equal to <code>1 g/(cm·s)</code> (cgs unit standard name <code>P</code>.
194     * 
195     * @see <a href="https://de.wikipedia.org/wiki/Poise">Wikipedia: Poise</a>
196     */
197    public static final Unit<DynamicViscosity> POISE = addUnit(GRAM.divide(CENTI(METRE).multiply(SECOND)).asType(DynamicViscosity.class), "Poise",
198            "P");
199
200    /**
201     * A unit of kinematic viscosity equal to <code>1 cm²/s</code> (cgs unit, standard name <code>St</code>).
202     */
203    public static final Unit<KinematicViscosity> STOKES = addUnit(CENTI(METRE).pow(2).divide(SECOND).asType(KinematicViscosity.class), "Stokes",
204            "St");
205
206    ////////////////
207    // Wavenumber //
208    ////////////////
209
210    /**
211     * A unit of wavenumber equal to <code>1/cm</code> (cgs unit, standard name <code>cm&#8315;&#185;</code>).
212     */
213    public static final Unit<KinematicViscosity> KAYSER = addUnit(ONE.divide(CENTIMETRE).asType(KinematicViscosity.class), "Kayser",
214            "cm\u207B\u00B9");
215
216    /////////////////////
217    // Collection View //
218    /////////////////////
219
220    public String getName() {
221        return SYSTEM_NAME;
222    }
223
224    @Override
225    public Unit<?> getUnit(String string) {
226        Objects.requireNonNull(string);
227        return this.getUnits().stream()
228                  .filter((u) -> string.equals(u.toString()))
229                  .findAny()
230                  .orElse(null);
231    }
232
233    /**
234     * Adds a new unit not mapped to any specified quantity type.
235     *
236     * @param unit
237     *            the unit being added.
238     * @return <code>unit</code>.
239     */
240    private static <U extends Unit<?>> U addUnit(U unit) {
241        INSTANCE.units.add(unit);
242        return unit;
243    }
244
245    /**
246     * Adds a new unit not mapped to any specified quantity type and puts a text as symbol or label.
247     *
248     * @param unit
249     *            the unit being added.
250     * @param name
251     *            the string to use as name
252     * @param text
253     *            the string to use as label or symbol
254     * @param isLabel
255     *            if the string should be used as a label or not
256     * @return <code>unit</code>.
257     */
258    private static <U extends Unit<?>> U addUnit(U unit, String name, String text, boolean isLabel) {
259        if (isLabel && text != null) {
260            SimpleUnitFormat.getInstance().label(unit, text);
261        }
262        if (name != null && unit instanceof AbstractUnit) {
263            return Helper.addUnit(INSTANCE.units, unit, name);
264        } else {
265            INSTANCE.units.add(unit);
266        }
267        return unit;
268    }
269
270    /**
271     * Adds a new unit not mapped to any specified quantity type and puts a text as symbol or label.
272     *
273     * @param unit
274     *            the unit being added.
275     * @param name
276     *            the string to use as name
277     * @param text
278     *            the string to use as label
279     * @return <code>unit</code>.
280     */
281    private static <U extends Unit<?>> U addUnit(U unit, String name, String text) {
282        return addUnit(unit, name, text, true);
283    }
284}