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