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