001/*
002 * ============================================================================
003 * Copyright © 2002-2023 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 * Licensed to the public under the agreements of the GNU Lesser General Public
007 * License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *      http://www.gnu.org/licenses/lgpl.html
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 * License for the specific language governing permissions and limitations
015 * under the License.
016 */
017
018package org.tquadrat.foundation.value;
019
020import static java.lang.String.format;
021import static java.util.Arrays.stream;
022import static org.apiguardian.api.API.Status.STABLE;
023import static org.tquadrat.foundation.lang.Objects.requireNotEmptyArgument;
024
025import java.math.BigDecimal;
026
027import org.apiguardian.api.API;
028import org.tquadrat.foundation.annotation.ClassVersion;
029import org.tquadrat.foundation.value.api.DimensionWithLinearConversion;
030
031/**
032 *  The various instances of masses and weights (although this is not really
033 *  the same, from a physical or scientific point of view ...).
034 *
035 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
036 *  @version $Id: Mass.java 1077 2023-10-14 23:00:23Z tquadrat $
037 *  @since 0.1.0
038 *
039 *  @UMLGraph.link
040 */
041@SuppressWarnings( "NewClassNamingConvention" )
042@ClassVersion( sourceVersion = "$Id: Mass.java 1077 2023-10-14 23:00:23Z tquadrat $" )
043@API( status = STABLE, since = "0.1.0" )
044public enum Mass implements DimensionWithLinearConversion
045{
046        /*------------------*\
047    ====** Enum Declaration **=================================================
048        \*------------------*/
049    /**
050     *  A milligram.
051     */
052    MILLIGRAM( new BigDecimal( "0.000001" ), "mg" ),
053
054    /**
055     *  An English grain. This unit is still in use to define the mass of
056     *  firearm bullets, arrow heads, or the explosives load for firearm
057     *  cartridges.
058     */
059    GRAIN( new BigDecimal( "0.00006479891" ), "gr." ),
060
061    /**
062     *  A metric carat; this is defined as 0.2 g; although no unit sign is
063     *  officially defined, the use of "ct" is widely accepted. That
064     *  is why we use it here as well.
065     */
066    CARAT( new BigDecimal( "0.0002" ), "ct" ),
067
068    /**
069     *  A gram.
070     */
071    GRAM( new BigDecimal( "0.001" ), "g" ),
072
073    /**
074     *  A dram (Avoirdupois), a 1/16 of an
075     *  {@linkplain #OUNCE ounce}.
076     */
077    DRAM( new BigDecimal( "0.001771845195312500" ), "dr." ),
078
079    /**
080     *  An ounce (Avoirdupois), a 1/16 of a
081     *  {@linkplain #POUND pound}.
082     */
083    OUNCE( new BigDecimal( "0.028349523125" ), "oz." ),
084
085    /**
086     *  A troy ounce (same as <i>Apothecaries Ounce</i>, as used for precious
087     *  metal.
088     */
089    TROY_OUNCE( new BigDecimal( "0.0311034768" ), "oz.tr." ),
090
091    /**
092     *  An imperial pound (Avoirdupois), 7000
093     *  {@linkplain #GRAIN grain}.
094     */
095    POUND( new BigDecimal( "0.45359237" ), "lb." ),
096
097    /**
098     *  A kilogram.
099     */
100    KILOGRAM( BigDecimal.ONE, "kg" ),
101
102    /**
103     *  <p>{@summary A stone; although abandoned since 1985, it will still be used in some
104     *  Commonwealth countries to determine the body weight.}</p>
105     *  <p>1&nbsp;st&nbsp;=&nbsp;14&nbsp;{@linkplain #POUND lb.}&nbsp;=&nbsp;224&nbsp;{@linkplain #OUNCE oz.}&nbsp;=&nbsp;3584&nbsp;{@linkplain #DRAM dr.}</p>
106     */
107    STONE( new BigDecimal( "6.35029318" ), "st" ),
108
109    /**
110     *  A short ton (2000 pound avoirdupois).
111     */
112    SHORT_TON( new BigDecimal( "907.18474" ), "to." ),
113
114    /**
115     *  A metric ton.
116     */
117    TON( new BigDecimal( "1000.0" ), "t" ),
118
119    /**
120     *  <p>{@summary The (estimated) mass of our sun.} This is often used when
121     *  comparing stars.</p>
122     */
123    @API( status = STABLE, since ="0.3.0" )
124    SOLAR_MASS( new BigDecimal( "1.989E+30" ), "SolarMass" ),
125
126    /**
127     *  <p>{@summary The mass of our planet Earth.} This is often used when
128     *  comparing masses of astronomical objects.</p>
129     */
130    @API( status = STABLE, since ="0.3.0" )
131    EARTH_MASS( new BigDecimal( "5.9722E+24" ), "EarthMass" );
132
133        /*------------*\
134    ====** Attributes **=======================================================
135        \*------------*/
136    /**
137     *  The factor.
138     */
139    private final BigDecimal m_Factor;
140
141    /**
142     *  The default precision.
143     */
144    private final int m_Precision;
145
146    /**
147     *  The unit string.
148     */
149    private final String m_UnitSymbol;
150
151        /*--------------*\
152    ====** Constructors **=====================================================
153        \*--------------*/
154    /**
155     *  Creates a new {@code Mass} instance with a default precision of zero
156     *  mantissa digits.
157     *
158     *  @param  factor  The factor.
159     *  @param  unitSymbol    The unit string.
160     */
161    private Mass( final BigDecimal factor, final String unitSymbol )
162    {
163        this( factor, unitSymbol, 0 );
164    }   //  Mass()
165
166    /**
167     *  Creates a new {@code Mass} instance.
168     *
169     *  @param  factor  The factor.
170     *  @param  unitSymbol    The unit string.
171     *  @param  precision   The default precision.
172     */
173    private Mass( final BigDecimal factor, final String unitSymbol, final int precision )
174    {
175        m_Factor = factor.stripTrailingZeros();
176        m_UnitSymbol = unitSymbol;
177        m_Precision = precision;
178    }   //  Mass()
179
180        /*---------*\
181    ====** Methods **==========================================================
182        \*---------*/
183    /**
184     *  {@inheritDoc}
185     */
186    @SuppressWarnings( "unchecked" )
187    @Override
188    public final Mass baseUnit() { return KILOGRAM; }
189
190    /**
191     *  {@inheritDoc}
192     */
193    @Override
194    public final BigDecimal factor() { return m_Factor; }
195
196    /**
197     *  Returns the {@code Weight} instance for the given unit.
198     *
199     *  @param  unitSymbol  The unit symbol.
200     *  @return The respective instance.
201     *  @throws IllegalArgumentException    The given unit is unknown.
202     */
203    public static final Mass forUnit( final String unitSymbol ) throws IllegalArgumentException
204    {
205        requireNotEmptyArgument( unitSymbol, "unitSymbol" );
206
207        final var retValue = stream( values() )
208            .filter( v -> v.unitSymbol().equals( unitSymbol ) )
209            .findFirst()
210            .orElseThrow( () -> new IllegalArgumentException( format( MSG_UnknownUnit, unitSymbol ) ) );
211
212        //---* Done *----------------------------------------------------------
213        return retValue;
214    }   //  forUnit()
215
216    /**
217     *  {@inheritDoc}
218     */
219    @Override
220    public final int getPrecision() { return m_Precision; }
221
222    /**
223     *  {@inheritDoc}
224     */
225    @Override
226    public final String unitSymbol() { return m_UnitSymbol; }
227}
228//  enum Mass
229
230/*
231 *  End of File
232 */