QuantityFormat.java
package org.djunits.formatter;
import org.djunits.quantity.LinearObjectDensity;
import org.djunits.quantity.Mass;
import org.djunits.unit.si.SIPrefixes;
import org.djutils.exceptions.Throw;
/**
* QuantityFormat stores the settings that influence both the value part and the unit part of an output string when formatting a
* quantity.
* <p>
* Copyright (c) 2026-2026 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
* for project information <a href="https://djunits.org" target="_blank">https://djunits.org</a>. The DJUNITS project is
* distributed under a <a href="https://djunits.org/docs/license.html" target="_blank">three-clause BSD-style license</a>.
* @author Alexander Verbraeck
*/
public class QuantityFormat extends Format<QuantityFormat, QuantityFormatContext>
{
/** The defaults (which can be changed). */
@SuppressWarnings("checkstyle:staticvariablename")
private static QuantityFormatContext DEFAULT = new QuantityFormatContext();
/**
* Construct a QuantityFormat object with a given context. Note that the context can be an existing context that is being
* modified or a default context.
* @param ctx the quantity format context to use
*/
protected QuantityFormat(final QuantityFormatContext ctx)
{
super(ctx);
}
/**
* Return an instance of QuantityFormat, initialized with the default values.
* @return an instance of QuantityFormat, initialized with the default values
*/
public static QuantityFormat instance()
{
return new QuantityFormat(DEFAULT.clone());
}
/**
* Return an instance of QuantityFormat with the DEFAULT values, which can be changed for all subsequent calls.
* @return an instance of QuantityFormat with the DEFAULT values
*/
public static QuantityFormat changeDefaults()
{
return new QuantityFormat(DEFAULT);
}
/**
* Reset the default values of QuantityFormat to their original values.
*/
public static void resetDefaults()
{
DEFAULT = new QuantityFormatContext();
}
/**
* Turn on the automatic allocation of the unit to its closest SI prefix. E.g., turn 20400 m into "20.4 km".
* @return QuantityFormat object for fluent design
*/
public QuantityFormat setAutoSiPrefix()
{
this.ctx.autoSiPrefix = true;
return this;
}
/**
* Turn on the automatic allocation of the unit to its closest SI prefix, in case the exponent of the 10-power in scientific
* notation is between minExponent and maxExponent, inclusive. E.g., format 20400 m as "20.4 km" after calling
* setAutoSiPrefix(-9,9) but format it as 20400 m after calling setAutoSiPrefix(-9,0). Note that the kg for {@link Mass} is
* associated with an exponent of 3, and the g with an exponent of 0. For the {@link LinearObjectDensity} that is expressed
* in /m, /km is associated with an exponent of 3 and /mm with an exponent of -3. Note that the minimum and maximum
* exponents are clamped between -30 and 30.
* @param minExponent minimum exponent for the 10-power in scientific notation to use SI prefixes for (inclusive)
* @param maxExponent maximum exponent for the 10-power in scientific notation to use SI prefixes for (inclusive)
* @return QuantityFormat object for fluent design
* @throws IllegalArgumentException when minExponent > maxExponent
*/
public QuantityFormat setAutoSiPrefix(final int minExponent, final int maxExponent)
{
Throw.when(minExponent > maxExponent, IllegalArgumentException.class, "minExponent %d > maxExponent %d", minExponent,
maxExponent);
this.ctx.autoSiPrefix = true;
this.ctx.autoSiMinExponent = Math.min(30, Math.max(-30, minExponent));
this.ctx.autoSiMaxExponent = Math.min(30, Math.max(-30, maxExponent));
return this;
}
/**
* Turn on the automatic allocation of the unit to its closest SI prefix, in case the exponent of the 10-power in scientific
* notation is between minExponent and maxExponent, inclusive. E.g., format 20400 m as "20.4 km" after calling
* setAutoSiPrefix("mu", "M") but format it as 20400 m after calling setAutoSiPrefix("mu", ""). Note that the kg for
* {@link Mass} is associated with the SI prefix "k", and the g with an SI prefix "". For the {@link LinearObjectDensity}
* 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
* maximum exponents are clamped between q (-30) and Q (30).
* @param minSiPrefix minimum SI prefix to use (inclusive)
* @param maxSiPrefix maximum SI prefix to use (inclusive)
* @return QuantityFormat object for fluent design
* @throws IllegalArgumentException when minSiPrefix > maxSiPrefix
* @throws IllegalArgumentException when the <code>minSiPrefix</code> or <code>maxSiPrefix</code> does not exist
*/
public QuantityFormat setAutoSiPrefix(final String minSiPrefix, final String maxSiPrefix)
{
int minExponent = SIPrefixes.getSiPrefix(minSiPrefix).getExponent();
int maxExponent = SIPrefixes.getSiPrefix(maxSiPrefix).getExponent();
Throw.when(minExponent > maxExponent, IllegalArgumentException.class, "minExponent %d > maxExponent %d", minExponent,
maxExponent);
this.ctx.autoSiPrefix = true;
this.ctx.autoSiMinExponent = Math.min(30, Math.max(-30, minExponent));
this.ctx.autoSiMaxExponent = Math.min(30, Math.max(-30, maxExponent));
return this;
}
/**
* Set whether it is allowed to use prefixes c, d, da, h in the autoSiPrefix.
* @param allowed to indicate whether it is allowed or not to use prefixes c, d, da, h in the autoSiPrefix
* @return QuantityFormat object for fluent design
*/
public QuantityFormat setAllowExponents12(final boolean allowed)
{
this.ctx.allowExponents12 = allowed;
return this;
}
/**
* Set that it is allowed to use prefixes c, d, da, h in the autoSiPrefix.
* @return QuantityFormat object for fluent design
*/
public QuantityFormat setAllowExponents12()
{
return setAllowExponents12(true);
}
}