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 area …
033 *
034 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
035 *  @version $Id: Area.java 1072 2023-09-30 20:44:38Z tquadrat $
036 *  @since 0.1.0
037 *
038 *  @UMLGraph.link
039 */
040@SuppressWarnings( "NewClassNamingConvention" )
041@ClassVersion( sourceVersion = "$Id: Area.java 1072 2023-09-30 20:44:38Z tquadrat $" )
042@API( status = STABLE, since = "0.1.0" )
043public enum Area implements DimensionWithLinearConversion
044{
045        /*------------------*\
046    ====** Enum Declaration **=================================================
047        \*------------------*/
048    /**
049     *  A square millimeter.
050     */
051    SQUARE_MILLIMETER( new BigDecimal( "0.000001" ), "mm^2" )
052    {
053        /**
054         *  {@inheritDoc}
055         */
056        @Override
057        public final String unitSymbolForPrinting() { return "mm²"; }
058    },
059
060    /**
061     *  A square centimeter.
062     */
063    SQUARE_CENTIMETER( new BigDecimal( "0.0001" ), "cm^2",1 )
064    {
065        /**
066         *  {@inheritDoc}
067         */
068        @Override
069        public final String unitSymbolForPrinting() { return "cm²"; }
070    },
071
072    /**
073     *  A square inch.
074     */
075    SQUARE_INCH( new BigDecimal( "0.00064516" ), "sqin" ),
076
077    /**
078     *  A square foot (144
079     *  {@linkplain #SQUARE_INCH square inch}).
080     */
081    SQUARE_FOOT( new BigDecimal( "0.092990304" ), "sqft" ),
082
083    /**
084     *  A square yard (9
085     *  {@linkplain #SQUARE_FOOT square feet}).
086     */
087    SQUARE_YARD( new BigDecimal( "0.83612736" ), "yd^2" )
088    {
089        /**
090         *  {@inheritDoc}
091         */
092        @Override
093        public final String unitSymbolForPrinting() { return "yd²"; }
094    },
095
096    /**
097     *  A square_meter.
098     */
099    SQUARE_METER( BigDecimal.ONE, "m^2", 1 )
100    {
101        /**
102         *  {@inheritDoc}
103         */
104        @Override
105        public final String unitSymbolForPrinting() { return "m²"; }
106    },
107
108    /**
109     *  An Ar (a unit for areas, used in the EU and Switzerland). It is 100
110     *  {@linkplain #SQUARE_METER square meter}.
111     */
112    AR( new BigDecimal( "100.0" ), "a" ),
113
114    /**
115     *  A %quot;Morgen", an ancient unit for areas that was used in
116     *  Germany (and is still used sometimes). It is 25
117     *  {@linkplain #AR ar},
118     *  2500
119     *  {@linkplain #SQUARE_METER square meter}
120     *  or ¼
121     *  {@linkplain #HEKTAR ha}.
122     */
123    MORGEN( new BigDecimal( "2500" ), "Mg" ),
124
125    /**
126     *  An acre.
127     */
128    ACRE( new BigDecimal( "4046.8564224" ), "ac" ),
129
130    /**
131     *  A hektar (a unit for areas, used in the EU and Switzerland). It is 100
132     *  {@linkplain #AR a}
133     *  or 10000
134     *  {@linkplain #SQUARE_METER square meter}.
135     */
136    HEKTAR( new BigDecimal( "10000.0" ), "ha" ),
137
138    /**
139     *  A square kilometer.
140     */
141    SQUARE_KILOMETER( new BigDecimal( "1000000.0" ), "km^2", 3 )
142    {
143        /**
144         *  {@inheritDoc}
145         */
146        @Override
147        public final String unitSymbolForPrinting() { return "km²"; }
148    },
149
150    /**
151     *  A square mile (1760 yard).
152     */
153    SQUARE_MILE( new BigDecimal( "2589988.110336" ), "sqmi" );
154
155        /*------------*\
156    ====** Attributes **=======================================================
157        \*------------*/
158    /**
159     *  The factor.
160     */
161    private final BigDecimal m_Factor;
162
163    /**
164     *  The default precision.
165     */
166    private final int m_Precision;
167
168    /**
169     *  The unit string.
170     */
171    private final String m_UnitSymbol;
172
173        /*--------------*\
174    ====** Constructors **=====================================================
175        \*--------------*/
176    /**
177     *  Creates a new {@code Area} instance, with a default precision of zero
178     *  mantissa digits.
179     *
180     *  @param  factor  The factor.
181     *  @param  unitSymbol    The unit symbol String.
182     */
183    private Area( final BigDecimal factor, final String unitSymbol )
184    {
185        this( factor, unitSymbol, 0 );
186    }   //  Area()
187
188    /**
189     *  Creates a new {@code Area} instance.
190     *
191     *  @param  factor  The factor.
192     *  @param  unitSymbol    The unit symbol String.
193     *  @param  precision   The default precision.
194     */
195    private Area( final BigDecimal factor, final String unitSymbol, final int precision )
196    {
197        m_Factor = factor.stripTrailingZeros();
198        m_UnitSymbol = unitSymbol;
199        m_Precision = precision;
200    }   //  Area()
201
202        /*---------*\
203    ====** Methods **==========================================================
204        \*---------*/
205    /**
206     *  {@inheritDoc}
207     */
208    @Override
209    @SuppressWarnings( "unchecked" )
210    public final Area baseUnit() { return SQUARE_METER; }
211
212    /**
213     *  {@inheritDoc}
214     */
215    @Override
216    public final BigDecimal factor() { return m_Factor; }
217
218    /**
219     *  Returns the {@code Area} instance for the given unit symbol.
220     *
221     *  @param  unitSymbol  The unit symbol.
222     *  @return The respective instance.
223     *  @throws IllegalArgumentException    The given unit is unknown.
224     */
225    public static final Area forUnit( final String unitSymbol ) throws IllegalArgumentException
226    {
227        requireNotEmptyArgument( unitSymbol, "unitSymbol" );
228
229        final var retValue = stream( values() )
230            .filter( v -> v.unitSymbol().equals( unitSymbol ) )
231            .findFirst()
232            .orElseThrow( () -> new IllegalArgumentException( format( MSG_UnknownUnit, unitSymbol ) ) );
233
234        //---* Done *----------------------------------------------------------
235        return retValue;
236    }   //  forUnit()
237
238    /**
239     *  {@inheritDoc}
240     */
241    @Override
242    public final int getPrecision() { return m_Precision; }
243
244    /**
245     *  {@inheritDoc}
246     */
247    @Override
248    public final String unitSymbol() { return m_UnitSymbol; }
249}
250//  enum Area
251
252/*
253 *  End of File
254 */