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 length …
033 *
034 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
035 *  @version $Id: Length.java 1072 2023-09-30 20:44:38Z tquadrat $
036 *  @since 0.1.0
037 *
038 *  @UMLGraph.link
039 */
040@ClassVersion( sourceVersion = "$Id: Length.java 1072 2023-09-30 20:44:38Z tquadrat $" )
041@API( status = STABLE, since = "0.1.0" )
042public enum Length implements DimensionWithLinearConversion
043{
044        /*------------------*\
045    ====** Enum Declaration **=================================================
046        \*------------------*/
047    /**
048     *  An Ångström.
049     */
050    @SuppressWarnings( {"NonAsciiCharacters", "UnnecessaryUnicodeEscape"} )
051    ÅNGSTRÖM( new BigDecimal( "0.0000000001" ), "\u212B" ),
052
053    /**
054     *  A nanometer.
055     */
056    NANOMETER( new BigDecimal( "0.000000001" ), "nm" ),
057
058    /**
059     *  A mikrometer.
060     */
061    MICROMETER( new BigDecimal( "0.000001" ), "µm" ),
062
063    /**
064     *  A typographical dot.
065     */
066    PICA( new BigDecimal( "0.0003527777777778" ), "pica", 1 ),
067
068    /**
069     *  A millimeter.
070     */
071    MILLIMETER( new BigDecimal( "0.001" ), "mm" ),
072
073    /**
074     *  A centimeter.
075     */
076    CENTIMETER( new BigDecimal( "0.01" ), "cm",1 ),
077
078    /**
079     *  An inch.
080     */
081    INCH( new BigDecimal( "0.0254" ), "in." ),
082
083    /**
084     *  A decimeter.
085     */
086    DECIMETER( new BigDecimal( "0.1" ), "dm" ),
087
088    /**
089     *  A foot (12
090     *  {@linkplain #INCH inch}).
091     */
092    FOOT( new BigDecimal( "0.3048" ), "ft." ),
093
094    /**
095     *  A yard (3
096     *  {@linkplain #FOOT feet}).
097     */
098    YARD( new BigDecimal( "0.9144" ), "yd." ),
099
100    /**
101     *  A meter.
102     */
103    METER( BigDecimal.ONE, "m", 1 ),
104
105    /**
106     *  A fathom.
107     */
108    FATHOM( new BigDecimal( "1.852" ), "fth." ),
109
110    /**
111     *  A cable length (1/10 of a
112     *  {@linkplain #NAUTICAL_MILE sea mile}
113     *  or 100
114     *  {@linkplain #FATHOM fathom}).
115     */
116    CABLE( new BigDecimal( "185.2" ), "cbl." ),
117
118    /**
119     *  A kilometer.
120     */
121    KILOMETER( new BigDecimal( "1000.0" ), "km", 1 ),
122
123    /**
124     *  A mile (1760 yard).
125     */
126    MILE( new BigDecimal( "1609.3440" ), "mi." ),
127
128    /**
129     *  A nautical or sea mile.
130     */
131    NAUTICAL_MILE( new BigDecimal( "1852.0" ), "NM" ),
132
133    /**
134     *  An astronomical unit.
135     */
136    ASTRONOMICAL_UNIT( new BigDecimal( "149597870700.0" ), "AU", 1 ),
137
138    /**
139     *  A light year.
140     */
141    LIGHTYEAR( new BigDecimal( "9460730472580800.0" ), "ly" ),
142
143    /**
144     *  A parsec, according to the definition of the IAU.
145     */
146    PARSEC( new BigDecimal( "3.0857E16" ), "pc", 2 );
147
148        /*------------*\
149    ====** Attributes **=======================================================
150        \*------------*/
151    /**
152     *  The factor.
153     */
154    private final BigDecimal m_Factor;
155
156    /**
157     *  The default precision.
158     */
159    private final int m_Precision;
160
161    /**
162     *  The unit string.
163     */
164    private final String m_UnitSymbol;
165
166        /*--------------*\
167    ====** Constructors **=====================================================
168        \*--------------*/
169    /**
170     *  Creates a new {@code Length} instance, with a default precision of zero
171     *  mantissa digits.
172     *
173     *  @param  factor  The factor.
174     *  @param  unitSymbol    The unit symbol String.
175     */
176    private Length( final BigDecimal factor, final String unitSymbol )
177    {
178        this( factor, unitSymbol, 0 );
179    }   //  Length()
180
181    /**
182     *  Creates a new {@code Length} instance.
183     *
184     *  @param  factor  The factor.
185     *  @param  unitSymbol    The unit symbol String.
186     *  @param  precision   The default precision.
187     */
188    private Length( final BigDecimal factor, final String unitSymbol, final int precision )
189    {
190        m_Factor = factor.stripTrailingZeros();
191        m_UnitSymbol = unitSymbol;
192        m_Precision = precision;
193    }   //  Length()
194
195        /*---------*\
196    ====** Methods **==========================================================
197        \*---------*/
198    /**
199     *  {@inheritDoc}
200     */
201    @Override
202    @SuppressWarnings( "unchecked" )
203    public final Length baseUnit() { return METER; }
204
205    /**
206     *  {@inheritDoc}
207     */
208    @Override
209    public final BigDecimal factor() { return m_Factor; }
210
211    /**
212     *  Returns the {@code Length} instance for the given unit symbol.
213     *
214     *  @param  unitSymbol  The unit symbol.
215     *  @return The respective instance.
216     *  @throws IllegalArgumentException    The given unit is unknown.
217     */
218    public static final Length forUnit( final String unitSymbol ) throws IllegalArgumentException
219    {
220        requireNotEmptyArgument( unitSymbol, "unitSymbol" );
221
222        final var retValue = stream( values() )
223            .filter( v -> v.unitSymbol().equals( unitSymbol ) )
224            .findFirst()
225            .orElseThrow( () -> new IllegalArgumentException( format( MSG_UnknownUnit, unitSymbol ) ) );
226
227        //---* Done *----------------------------------------------------------
228        return retValue;
229    }   //  forUnit()
230
231    /**
232     *  {@inheritDoc}
233     */
234    @Override
235    public final int getPrecision() { return m_Precision; }
236
237    /**
238     *  {@inheritDoc}
239     */
240    @Override
241    public final String unitSymbol() { return m_UnitSymbol; }
242}
243//  enum Length
244
245/*
246 *  End of File
247 */