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.api;
019
020import static org.apiguardian.api.API.Status.STABLE;
021
022import java.io.Serializable;
023import java.math.BigDecimal;
024import java.util.function.UnaryOperator;
025
026import org.apiguardian.api.API;
027import org.tquadrat.foundation.annotation.ClassVersion;
028
029/**
030 *  <p>{@summary The implementations of this interface are used to give
031 *  (numerical) values a dimension and a measuring unit.} So {@code 3.1415} is
032 *  just a number, but it could also stand for a length
033 *  ({@code 3.1415&nbsp;m}), a time ({@code 3.1415&nbsp;s}) or even the fuel
034 *  consumption of a car ({@code 3.1415&nbsp;l/100&nbsp;km}). Depending on the
035 *  dimension, different values could be equal:</p>
036 *  <pre><code>1.0&nbsp;m == 100.0&nbsp;cm</code></pre>
037 *  <p>and should be treated as such.</p>
038 *  <p>This interface should be implemented as
039 *  {@link java.lang.Enum enum}s,
040 *  where the enum values are the units, and as such they should provide a
041 *  method to retrieve an {@code enum} value (a unit) by the respective
042 *  {@linkplain #unitSymbol() symbol}.</p>
043 *
044 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
045 *  @version $Id: Dimension.java 1072 2023-09-30 20:44:38Z tquadrat $
046 *  @since 0.1.0
047 *
048 *  @UMLGraph.link
049 */
050@ClassVersion( sourceVersion = "$Id: Dimension.java 1072 2023-09-30 20:44:38Z tquadrat $" )
051@API( status = STABLE, since = "0.1.0" )
052public interface Dimension extends Serializable
053{
054        /*-----------*\
055    ====** Constants **========================================================
056        \*-----------*/
057    /**
058     *  Message: Unknown Unit.
059     */
060    public static final String MSG_UnknownUnit = "Unknown unit: %s";
061
062        /*---------*\
063    ====** Methods **==========================================================
064        \*---------*/
065    /**
066     *  <p>{@summary Returns the base unit.}</p>
067     *  <p>E.g. for length, the base unit would be Meter (m), for mass, it is
068     *  Kilogram (kg), and so on.</p>
069     *
070     *  @param  <D> The implementing class for the interface.
071     *  @return The base unit.
072     */
073    public <D extends Dimension> D baseUnit();
074
075    /**
076     *  {@inheritDoc}
077     *  <p>Dimensions are equal when they are identical; therefore they
078     *  should be implemented as <i>Multitons</i> (constants of the
079     *  implementing class, without the option to create additional instances
080     *  on runtime).</p>
081     */
082    @Override
083    public boolean equals( Object o );
084
085    /**
086     *  <p>{@summary Returns the conversion that is used to convert a value
087     *  from the base unit to this unit.}</p>
088     *
089     *  @return The conversion.
090     */
091    public UnaryOperator<BigDecimal> fromBase();
092
093    /**
094     *  Returns the default precision for this unit that is used when the
095     *  respective value is converted to a String.
096     *
097     *  @return The mantissa length for a value with this unit.
098     */
099    public default int getPrecision() { return 1; }
100
101    /**
102     *  <p>{@summary Returns the conversion that is used to convert a value
103     *  from this unit to the base unit.}</p>
104     *
105     *  @return The conversion.
106     */
107    public UnaryOperator<BigDecimal> toBase();
108
109    /**
110     *  Returns the internal name of the dimension.
111     *
112     *  @return The internal name.
113     */
114    public String name();
115
116    /**
117     *  {@inheritDoc}
118     *
119     *  @note {@code toString()} should be implemented to return the result of
120     *      {@link #unitSymbol()}
121     *      instead of
122     *      {@link Enum#name()}, as it would be the default for {@code enum}s.
123     */
124    @Override
125    public String toString();
126
127    /**
128     *  <p>{@summary Returns the unit symbol for the dimension as a single line
129     *  string.}</p>
130     *  <p>For a length, this would be &quot;m&quot;, for a speed
131     *  &quot;km/h&quot;, and for an acceleration, it could be
132     *  &quot;m/(s^2)&quot;.</p>
133     *
134     *  @return The unit.
135     */
136    public String unitSymbol();
137
138    /**
139     *  <p>{@summary Returns the unit symbol for the dimension still as a
140     *  single line string, but with special characters.}</p>
141     *  <p>For a length, this would still be &quot;m&quot;, for a speed
142     *  &quot;km/h&quot;, but for an acceleration, it would be
143     *  &quot;m/s²&quot;.</p>
144     *  <p>For most dimensions, this is the same as the return value of
145     *  {@link #unitSymbol()}.</p>
146     *
147     *  @return The unit beautified for printing.
148     */
149    public default String unitSymbolForPrinting() { return unitSymbol(); }
150}
151//  interface Dimension
152
153/*
154 *  End of File
155 */