View Javadoc
1   package org.djunits.formatter;
2   
3   import org.djunits.quantity.LinearObjectDensity;
4   import org.djunits.quantity.Mass;
5   import org.djunits.unit.si.SIPrefixes;
6   import org.djutils.exceptions.Throw;
7   
8   /**
9    * QuantityFormat stores the settings that influence both the value part and the unit part of an output string when formatting a
10   * quantity.
11   * <p>
12   * Copyright (c) 2026-2026 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
13   * for project information <a href="https://djunits.org" target="_blank">https://djunits.org</a>. The DJUNITS project is
14   * distributed under a <a href="https://djunits.org/docs/license.html" target="_blank">three-clause BSD-style license</a>.
15   * @author Alexander Verbraeck
16   */
17  public class QuantityFormat extends Format<QuantityFormat, QuantityFormatContext>
18  {
19      /** The defaults (which can be changed). */
20      @SuppressWarnings("checkstyle:staticvariablename")
21      private static QuantityFormatContext DEFAULT = new QuantityFormatContext();
22  
23      /**
24       * Construct a QuantityFormat object with a given context. Note that the context can be an existing context that is being
25       * modified or a default context.
26       * @param ctx the quantity format context to use
27       */
28      protected QuantityFormat(final QuantityFormatContext ctx)
29      {
30          super(ctx);
31      }
32  
33      /**
34       * Return an instance of QuantityFormat, initialized with the default values.
35       * @return an instance of QuantityFormat, initialized with the default values
36       */
37      public static QuantityFormat instance()
38      {
39          return new QuantityFormat(DEFAULT.clone());
40      }
41  
42      /**
43       * Return an instance of QuantityFormat with the DEFAULT values, which can be changed for all subsequent calls.
44       * @return an instance of QuantityFormat with the DEFAULT values
45       */
46      public static QuantityFormat changeDefaults()
47      {
48          return new QuantityFormat(DEFAULT);
49      }
50  
51      /**
52       * Reset the default values of QuantityFormat to their original values.
53       */
54      public static void resetDefaults()
55      {
56          DEFAULT = new QuantityFormatContext();
57      }
58  
59      /**
60       * Turn on the automatic allocation of the unit to its closest SI prefix. E.g., turn 20400 m into "20.4 km".
61       * @return QuantityFormat object for fluent design
62       */
63      public QuantityFormat setAutoSiPrefix()
64      {
65          this.ctx.autoSiPrefix = true;
66          return this;
67      }
68  
69      /**
70       * Turn on the automatic allocation of the unit to its closest SI prefix, in case the exponent of the 10-power in scientific
71       * notation is between minExponent and maxExponent, inclusive. E.g., format 20400 m as "20.4 km" after calling
72       * setAutoSiPrefix(-9,9) but format it as 20400 m after calling setAutoSiPrefix(-9,0). Note that the kg for {@link Mass} is
73       * associated with an exponent of 3, and the g with an exponent of 0. For the {@link LinearObjectDensity} that is expressed
74       * in /m, /km is associated with an exponent of 3 and /mm with an exponent of -3. Note that the minimum and maximum
75       * exponents are clamped between -30 and 30.
76       * @param minExponent minimum exponent for the 10-power in scientific notation to use SI prefixes for (inclusive)
77       * @param maxExponent maximum exponent for the 10-power in scientific notation to use SI prefixes for (inclusive)
78       * @return QuantityFormat object for fluent design
79       * @throws IllegalArgumentException when minExponent &gt; maxExponent
80       */
81      public QuantityFormat setAutoSiPrefix(final int minExponent, final int maxExponent)
82      {
83          Throw.when(minExponent > maxExponent, IllegalArgumentException.class, "minExponent %d > maxExponent %d", minExponent,
84                  maxExponent);
85          this.ctx.autoSiPrefix = true;
86          this.ctx.autoSiMinExponent = Math.min(30, Math.max(-30, minExponent));
87          this.ctx.autoSiMaxExponent = Math.min(30, Math.max(-30, maxExponent));
88          return this;
89      }
90  
91      /**
92       * Turn on the automatic allocation of the unit to its closest SI prefix, in case the exponent of the 10-power in scientific
93       * notation is between minExponent and maxExponent, inclusive. E.g., format 20400 m as "20.4 km" after calling
94       * setAutoSiPrefix("mu", "M") but format it as 20400 m after calling setAutoSiPrefix("mu", ""). Note that the kg for
95       * {@link Mass} is associated with the SI prefix "k", and the g with an SI prefix "". For the {@link LinearObjectDensity}
96       * that is expressed in /m, /km is associated with an SI prefix "k" and /mm with an SI prefix "m". Note that the minimum and
97       * maximum exponents are clamped between q (-30) and Q (30).
98       * @param minSiPrefix minimum SI prefix to use (inclusive)
99       * @param maxSiPrefix maximum SI prefix to use (inclusive)
100      * @return QuantityFormat object for fluent design
101      * @throws IllegalArgumentException when minSiPrefix &gt; maxSiPrefix
102      * @throws IllegalArgumentException when the <code>minSiPrefix</code> or <code>maxSiPrefix</code> does not exist
103      */
104     public QuantityFormat setAutoSiPrefix(final String minSiPrefix, final String maxSiPrefix)
105     {
106         int minExponent = SIPrefixes.getSiPrefix(minSiPrefix).getExponent();
107         int maxExponent = SIPrefixes.getSiPrefix(maxSiPrefix).getExponent();
108         Throw.when(minExponent > maxExponent, IllegalArgumentException.class, "minExponent %d > maxExponent %d", minExponent,
109                 maxExponent);
110         this.ctx.autoSiPrefix = true;
111         this.ctx.autoSiMinExponent = Math.min(30, Math.max(-30, minExponent));
112         this.ctx.autoSiMaxExponent = Math.min(30, Math.max(-30, maxExponent));
113         return this;
114     }
115 
116     /**
117      * Set whether it is allowed to use prefixes c, d, da, h in the autoSiPrefix.
118      * @param allowed to indicate whether it is allowed or not to use prefixes c, d, da, h in the autoSiPrefix
119      * @return QuantityFormat object for fluent design
120      */
121     public QuantityFormat setAllowExponents12(final boolean allowed)
122     {
123         this.ctx.allowExponents12 = allowed;
124         return this;
125     }
126     
127     /**
128      * Set that it is allowed to use prefixes c, d, da, h in the autoSiPrefix.
129      * @return QuantityFormat object for fluent design
130      */
131     public QuantityFormat setAllowExponents12()
132     {
133         return setAllowExponents12(true);
134     }
135 
136 }