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 volume …
033 *
034 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
035 *  @version $Id: Volume.java 1073 2023-10-01 11:08:51Z tquadrat $
036 *  @since 0.1.0
037 *
038 *  @UMLGraph.link
039 */
040@ClassVersion( sourceVersion = "$Id: Volume.java 1073 2023-10-01 11:08:51Z tquadrat $" )
041@API( status = STABLE, since = "0.1.0" )
042public enum Volume implements DimensionWithLinearConversion
043{
044        /*------------------*\
045    ====** Enum Declaration **=================================================
046        \*------------------*/
047    /**
048     *  A cubic millimeter.
049     */
050    CUBIC_MILLIMETER( new BigDecimal( "0.000000001" ), "mm^3" )
051    {
052        /**
053         *  {@inheritDoc}
054         */
055        @Override
056        public final String unitSymbolForPrinting() { return "mm³"; }
057    },
058
059    /**
060     *  A micro liter.
061     */
062    MICRO_LITER( new BigDecimal( "0.000000001" ), "µl" ),
063
064    /**
065     *  A cubic centimeter.
066     */
067    CUBIC_CENTIMETER( new BigDecimal( "0.000001" ), "cm^3" )
068    {
069        /**
070         *  {@inheritDoc}
071         */
072        @Override
073        public final String unitSymbolForPrinting() { return "cm³"; }
074    },
075
076    /**
077     *  A milliliter.
078     */
079    MILLI_LITER( new BigDecimal( "0.000001" ), "ml" ),
080
081    /**
082     *  A centiliter.
083     */
084    CENTI_LITER( new BigDecimal( "0.00001" ), "cl" ),
085
086    /**
087     *  A cubic inch.
088     */
089    CUBIC_INCH( new BigDecimal( "0.000016387064" ), "in^3",1 )
090    {
091        /**
092         *  {@inheritDoc}
093         */
094        @Override
095        public final String unitSymbolForPrinting() { return "in³"; }
096    },
097
098    /**
099     *  An imperial fluid ounce.
100     */
101    FLUID_OUNCE_IMPERIAL( new BigDecimal( "0.0000284130625" ), "floz" ),
102
103    /**
104     *  A deciliter.
105     */
106    DECI_LITER( new BigDecimal( "0.0001" ), "dl" ),
107
108    /**
109     *  A pint liquid imperial.
110     */
111    PINT_LIQUID_IMPERIAL( new BigDecimal( "0.00056826128524935" ), "pt",1 ),
112
113    /**
114     *  A cubic decimeter.
115     */
116    CUBIC_DECIMETER( new BigDecimal( "0.001" ), "dm^3",1 )
117    {
118        /**
119         *  {@inheritDoc}
120         */
121        @Override
122        public final String unitSymbolForPrinting() { return "dm³"; }
123    },
124
125    /**
126     *  A liter.
127     */
128    LITER( new BigDecimal( "0.001" ), "l",1 ),
129
130    /**
131     *  A bucket ("Eimer" in German). Obviously, this is not an
132     *  official unit for a volume, but it is used quit often on a colloquial
133     *  basis in Germany and other German-speaking countries to describe the
134     *  amount of 10 liters.
135     */
136    BUCKET( new BigDecimal( "0.01" ), "Eimer" ),
137
138    /**
139     *  A US (liquid) gallon.
140     */
141    US_GALLON( new BigDecimal( "0.003785411784" ), "USGallon",1 )
142    {
143        /**
144         *  {@inheritDoc}
145         */
146        @Override
147        public final String unitSymbolForPrinting() { return "US Gallon"; }
148    },
149
150    /**
151     *  An imperial gallon.
152     */
153    GALLON( new BigDecimal( "0.00454609" ), "gal",1 ),
154
155    /**
156     *  A cubic foot.
157     */
158    CUBIC_FOOT( new BigDecimal( "0.028316846592" ), "ft^3" )
159    {
160        /**
161         *  {@inheritDoc}
162         */
163        @Override
164        public final String unitSymbolForPrinting() { return "ft³"; }
165    },
166
167    /**
168     *  A hekto liter.
169     */
170    HEKTO_LITER( new BigDecimal( "0.1" ), "hl",1 ),
171
172    /**
173     *  A barrel as used for mineral oil.
174     */
175    BARREL_OIL( new BigDecimal( "0.158987294928" ), "barrel(oil)" )
176    {
177        /**
178         *  {@inheritDoc}
179         */
180        @Override
181        public final String unitSymbolForPrinting() { return "barrel (oil)"; }
182    },
183
184    /**
185     *  An imperial barrel.
186     */
187    IMPERIAL_BARREL( new BigDecimal( "0.16365924" ), "barrel(imperial)",1 )
188    {
189        /**
190         *  {@inheritDoc}
191         */
192        @Override
193        public final String unitSymbolForPrinting() { return "barrel (imperial)"; }
194    },
195
196    /**
197     *  A cubic yard.
198     */
199    CUBIC_YARD( new BigDecimal( "0.764554857984" ), "yd^3" )
200    {
201        /**
202         *  {@inheritDoc}
203         */
204        @Override
205        public final String unitSymbolForPrinting() { return "yd³"; }
206    },
207
208    /**
209     *  A cubic meter.
210     */
211    CUBIC_METER( BigDecimal.ONE, "m^3",3 )
212    {
213        /**
214         *  {@inheritDoc}
215         */
216        @Override
217        public final String unitSymbolForPrinting() { return "m³"; }
218    },
219
220    /**
221     *  A "Festmeter"; this is used (in Germany) to specify an amount
222     *  of wood.
223     */
224    FESTMETER( BigDecimal.ONE, "Festmeter",1 ),
225
226    /**
227     *  <p>{@summary A ton as used by <i>Traveller</i>® to specify the volume
228     *  of a starship or other space going vessels or orbital installations.}
229     *  It is defined as the volume of one metric ton or 1000&nbsp;kg of liquid
230     *  hydrogen (H<sub>2</sub>) with a specific density of
231     *  71&nbsp;kg/m<sup>3</sup>.</p>
232     *  <p>The <i>Traveller</i>® literature also uses a value of
233     *  13.5&nbsp;m<sup>3</sup>, based on the dimensions used with ship floor
234     *  plans: a square on such a plan has a side length of 1.5&nbsp;m and the
235     *  room height is taken as 3&nbsp;m, with each square is the equivalent of
236     *  half a ton (or 6.75&nbsp;m<sup>3</sup>). For mapping purposes this is a
237     *  valid approximation.</p>
238     */
239    TON( new BigDecimal( "14.084507"), "ton" ),
240
241    /**
242     *  A cubic kilometer.
243     */
244    CUBIC_KILO_METER( new BigDecimal( "1000000000" ), "km^3",3 )
245    {
246        /**
247         *  {@inheritDoc}
248         */
249        @Override
250        public final String unitSymbolForPrinting() { return "km³"; }
251    },
252
253    /**
254     *  A cubic mile.
255     */
256    CUBIC_MILE( new BigDecimal( "4168181825.4406" ), "mi^3" )
257    {
258        /**
259         *  {@inheritDoc}
260         */
261        @Override
262        public final String unitSymbolForPrinting() { return "mi³"; }
263    };
264
265        /*------------*\
266    ====** Attributes **=======================================================
267        \*------------*/
268    /**
269     *  The factor.
270     */
271    private final BigDecimal m_Factor;
272
273    /**
274     *  The default precision.
275     */
276    private final int m_Precision;
277
278    /**
279     *  The unit string.
280     */
281    private final String m_UnitSymbol;
282
283        /*--------------*\
284    ====** Constructors **=====================================================
285        \*--------------*/
286    /**
287     *  Creates a new {@code Volume} instance, with a default precision of zero
288     *  mantissa digits.
289     *
290     *  @param  factor  The factor.
291     *  @param  unitSymbol    The unit symbol String.
292     */
293    private Volume( final BigDecimal factor, final String unitSymbol )
294    {
295        this( factor, unitSymbol, 0 );
296    }   //  Volume()
297
298    /**
299     *  Creates a new {@code Volume} instance.
300     *
301     *  @param  factor  The factor.
302     *  @param  unitSymbol    The unit symbol String.
303     *  @param  precision   The default precision.
304     */
305    private Volume( final BigDecimal factor, final String unitSymbol, final int precision )
306    {
307        m_Factor = factor.stripTrailingZeros();
308        m_UnitSymbol = unitSymbol;
309        m_Precision = precision;
310    }   //  Volume()
311
312        /*---------*\
313    ====** Methods **==========================================================
314        \*---------*/
315    /**
316     *  {@inheritDoc}
317     */
318    @Override
319    @SuppressWarnings( "unchecked" )
320    public final Volume baseUnit() { return CUBIC_METER; }
321
322    /**
323     *  {@inheritDoc}
324     */
325    @Override
326    public final BigDecimal factor() { return m_Factor; }
327
328    /**
329     *  Returns the {@code Volume} instance for the given unit symbol.
330     *
331     *  @param  unitSymbol  The unit symbol.
332     *  @return The respective instance.
333     *  @throws IllegalArgumentException    The given unit is unknown.
334     */
335    public static final Volume forUnit( final String unitSymbol ) throws IllegalArgumentException
336    {
337        requireNotEmptyArgument( unitSymbol, "unitSymbol" );
338
339        final var retValue = stream( values() )
340            .filter( v -> v.unitSymbol().equals( unitSymbol ) )
341            .findFirst()
342            .orElseThrow( () -> new IllegalArgumentException( format( MSG_UnknownUnit, unitSymbol ) ) );
343
344        //---* Done *----------------------------------------------------------
345        return retValue;
346    }   //  forUnit()
347
348    /**
349     *  {@inheritDoc}
350     */
351    @Override
352    public final int getPrecision() { return m_Precision; }
353
354    /**
355     *  {@inheritDoc}
356     */
357    @Override
358    public final String unitSymbol() { return m_UnitSymbol; }
359}
360//  enum Volume
361
362/*
363 *  End of File
364 */