Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ Example: "I need to convert between grains per pound and kg/kg but Unitility doe
**Describe the solution you'd like**
A clear and concise description of what you would like to see implemented.
Example: "Add a `GrainsPerPound` unit and extend `HumidityRatio` to support parsing from this unit."
Provide information what is current behaviour, and what is the expected result.

**Describe alternatives you've considered**
Have you tried working around the issue?
Example: "I wrote a custom unit / custom parsing factory, but it would be great to have this natively in Unitility."

**Additional context**
Include any references, code snippets, or use cases that explain why this feature is valuable.
Provide list of physical quantities or additional units you need, so they could be added in next release.
112 changes: 75 additions & 37 deletions README.md

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

<properties>
<!-- MODULES VERSION -->
<project.version>2.11.2</project.version>
<project.version>3.0.0</project.version>

<!-- Maven Properties -->
<maven.compiler.source>17</maven.compiler.source>
Expand All @@ -56,26 +56,26 @@
<!-- Jackson module -->
<jackson-databind.version>2.19.2</jackson-databind.version>
<!-- SpringBoot module -->
<spring-boot-starter-web.version>3.5.4</spring-boot-starter-web.version>
<spring-boot-starter-web.version>3.5.6</spring-boot-starter-web.version>
<!-- Quarkus module -->
<quarkus-version>3.24.5</quarkus-version>
<quarkus-version>3.27.0</quarkus-version>
<!-- Jakarta validation module -->
<jakarta.validation-api.version>3.1.1</jakarta.validation-api.version>
<jakarta.el.version>6.0.1</jakarta.el.version>
<hibernate-validator.version>9.0.1.Final</hibernate-validator.version>

<!-- Test dependencies versions -->
<jacoco.version>0.8.13</jacoco.version>
<junit-jupiter.version>5.13.4</junit-jupiter.version>
<assertj-core.version>3.27.3</assertj-core.version>
<junit-jupiter.version>6.0.0</junit-jupiter.version>
<assertj-core.version>3.27.6</assertj-core.version>

<!-- Plugin versions -->
<flatten-maven-plugin.version>1.7.2</flatten-maven-plugin.version>
<maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version>
<flatten-maven-plugin.version>1.7.3</flatten-maven-plugin.version>
<maven-javadoc-plugin.version>3.12.0</maven-javadoc-plugin.version>
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
<nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version>
<maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>
<jandex-maven-plugin.version>3.4.0</jandex-maven-plugin.version>
<maven-surefire-plugin.version>3.5.4</maven-surefire-plugin.version>
<jandex-maven-plugin.version>3.5.0</jandex-maven-plugin.version>

<!-- Sonar Cloud Properties-->
<sonar.organization>synerset</sonar.organization>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.synerset.unitility.unitsystem;

public class Constants {

private Constants() {
throw new IllegalStateException("Utility class");
}

// SI Prefix Factors
public static final double PICO = 1e-12;
public static final double NANO = 1e-9;
public static final double MICRO = 1e-6;
public static final double MILLI = 1e-3;
public static final double CENTI = 1e-2;
public static final double DECI = 1e-1;

public static final double DECA = 1e1;
public static final double HECTO = 1e2;
public static final double KILO = 1e3;
public static final double MEGA = 1e6;
public static final double GIGA = 1e9;
public static final double TERA = 1e12;

// Physical constants
public static final double GRAVITY_SI = 9.80665;

// Canonical Time
public static final double SECONDS_IN_MINUTE = 60;
public static final double SECONDS_IN_HOUR = 3600;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package com.synerset.unitility.unitsystem.acoustic;

import com.synerset.unitility.unitsystem.CalculableQuantity;
import com.synerset.unitility.unitsystem.thermodynamic.PowerUnit;

import java.util.Objects;

public class SoundPower implements CalculableQuantity<PowerUnit, SoundPower> {

private final double value;
private final double baseValue;
private final PowerUnit unitType;

public SoundPower(double value, PowerUnit unitType) {
this.unitType = unitType == null ? SoundPowerUnits.WATT : unitType;
this.value = value;
this.baseValue = this.unitType.toValueInBaseUnit(value);
}

// Static factories
public static SoundPower of(double value, PowerUnit unit) {
return new SoundPower(value, unit);
}

public static SoundPower of(double value, String unitSymbol) {
PowerUnit resolvedUnit = SoundPowerUnits.fromSymbol(unitSymbol);
return new SoundPower(value, resolvedUnit);
}

public static SoundPower ofWatts(double value) {
return new SoundPower(value, SoundPowerUnits.WATT);
}

public static SoundPower ofDecibels(double value) {
return new SoundPower(value, SoundPowerUnits.DECIBEL);
}

@Override
public double getValue() {
return value;
}

@Override
public double getBaseValue() {
return baseValue;
}

@Override
public PowerUnit getUnit() {
return unitType;
}

@Override
public SoundPower toBaseUnit() {
return of(baseValue, SoundPowerUnits.WATT);
}

@Override
public SoundPower toUnit(PowerUnit targetUnit) {
double targetVal = targetUnit.fromValueInBaseUnit(baseValue);
return of(targetVal, targetUnit);
}

@Override
public SoundPower toUnit(String targetSymbol) {
return toUnit(SoundPowerUnits.fromSymbol(targetSymbol));
}

@Override
public SoundPower withValue(double value) {
return of(value, unitType);
}

// Convenience converters
public SoundPower toWatts() {
return toUnit(SoundPowerUnits.WATT);
}

public SoundPower toDecibels() {
return toUnit(SoundPowerUnits.DECIBEL);
}

public double getInWatts() {
return getInUnit(SoundPowerUnits.WATT);
}

public double getInDecibels() {
return getInUnit(SoundPowerUnits.DECIBEL);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SoundPower that)) return false;
return Double.compare(that.baseValue, baseValue) == 0
&& Objects.equals(unitType.getBaseUnit(), that.unitType.getBaseUnit());
}

@Override
public int hashCode() {
return Objects.hash(baseValue, unitType.getBaseUnit());
}

@Override
public String toString() {
return value + " " + unitType.getSymbol();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.synerset.unitility.unitsystem.acoustic;

import com.synerset.unitility.unitsystem.exceptions.UnitSystemParseException;
import com.synerset.unitility.unitsystem.thermodynamic.PowerUnit;
import com.synerset.unitility.unitsystem.thermodynamic.PowerUnits;
import com.synerset.unitility.unitsystem.util.StringTransformer;

import java.util.function.DoubleUnaryOperator;

public enum SoundPowerUnits implements PowerUnit {
// Assumed reference power = 1E-12 W.

WATT("W", val -> val, val -> val),
DECIBEL("dB", db -> Math.pow(10.0, db / 10.0) * 1E-12, w -> 10.0 * Math.log10(w / 1E-12));

private final String symbol;
private final DoubleUnaryOperator toBaseConverter;
private final DoubleUnaryOperator fromBaseToUnitConverter;

SoundPowerUnits(String symbol, DoubleUnaryOperator toBaseConverter, DoubleUnaryOperator fromBaseToUnitConverter) {
this.symbol = symbol;
this.toBaseConverter = toBaseConverter;
this.fromBaseToUnitConverter = fromBaseToUnitConverter;
}

@Override
public String getSymbol() {
return symbol;
}

@Override
public SoundPowerUnits getBaseUnit() {
return WATT;
}

@Override
public double toValueInBaseUnit(double valueInThisUnit) {
return toBaseConverter.applyAsDouble(valueInThisUnit);
}

@Override
public double fromValueInBaseUnit(double valueInBaseUnit) {
return fromBaseToUnitConverter.applyAsDouble(valueInBaseUnit);
}

public static PowerUnit fromSymbol(String rawSymbol) {
if (rawSymbol == null || rawSymbol.isBlank()) {
return WATT;
}
String requestedSymbol = unifySymbol(rawSymbol);

for (SoundPowerUnits unit : values()) {
String currentSymbol = unifySymbol(unit.getSymbol());
if (currentSymbol.equalsIgnoreCase(requestedSymbol)) {
return unit;
}
}

PowerUnit foundTargetUnit = PowerUnits.fromSymbol(requestedSymbol);

if (foundTargetUnit == null) {
throw new UnitSystemParseException("Unsupported unit symbol: " + "{" + rawSymbol + "}." + " Target class: "
+ SoundPowerUnits.class.getSimpleName());
}

return foundTargetUnit;
}

private static String unifySymbol(String inputString) {
return StringTransformer.of(inputString)
.trimLowerAndClean()
.unifyMultiAndDiv()
.replace("dbl", "db")
.toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.synerset.unitility.unitsystem.acoustic;

import com.synerset.unitility.unitsystem.CalculableQuantity;
import com.synerset.unitility.unitsystem.thermodynamic.PressureUnit;

import java.util.Objects;

public class SoundPressure implements CalculableQuantity<PressureUnit, SoundPressure> {

private final double value;
private final double baseValue;
private final PressureUnit unit;

public SoundPressure(double value, PressureUnit unit) {
this.unit = unit == null ? SoundPressureUnits.PASCAL : unit;
this.value = value;
this.baseValue = this.unit.toValueInBaseUnit(value);
}

public static SoundPressure of(double value, PressureUnit unit) {
return new SoundPressure(value, unit);
}

public static SoundPressure of(double value, String unitSymbol) {
PressureUnit resolvedUnit = SoundPressureUnits.fromSymbol(unitSymbol);
return new SoundPressure(value, resolvedUnit);
}

public static SoundPressure ofPascals(double value) {
return new SoundPressure(value, SoundPressureUnits.PASCAL);
}

public static SoundPressure ofDecibels(double value) {
return new SoundPressure(value, SoundPressureUnits.DECIBEL);
}

@Override
public SoundPressure toBaseUnit() {
return of(baseValue, SoundPressureUnits.PASCAL);
}

@Override
public SoundPressure toUnit(PressureUnit targetUnit) {
double targetVal = targetUnit.fromValueInBaseUnit(baseValue);
return of(targetVal, targetUnit);
}

@Override
public SoundPressure toUnit(String targetSymbol) {
return toUnit(SoundPressureUnits.fromSymbol(targetSymbol));
}

@Override
public SoundPressure withValue(double value) {
return of(value, unit);
}

public SoundPressure toPascals() {
return toUnit(SoundPressureUnits.PASCAL);
}

public SoundPressure toDecibels() {
return toUnit(SoundPressureUnits.DECIBEL);
}

public double getInPascals() {
return getInUnit(SoundPressureUnits.PASCAL);
}

public double getInDecibels() {
return getInUnit(SoundPressureUnits.DECIBEL);
}

@Override
public double getValue() {
return value;
}

@Override
public double getBaseValue() {
return baseValue;
}

@Override
public PressureUnit getUnit() {
return unit;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SoundPressure that)) return false;
return Double.compare(that.baseValue, baseValue) == 0
&& Objects.equals(unit.getBaseUnit(), that.unit.getBaseUnit());
}

@Override
public int hashCode() {
return Objects.hash(baseValue, unit.getBaseUnit());
}

@Override
public String toString() {
return value + " " + unit.getSymbol();
}
}
Loading