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 config/checkstyle/checkstyle-suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
<suppress files="FmpIsin.java" checks="AvoidInlineConditionals"/> <!-- isValidLuhn() -->
<suppress files="FmpKeyMetric.java" checks="AbbreviationAsWordInName"/> <!-- evToEBITDA, netDebtToEBITDA -->
<suppress files="FmpKeyMetricTtm.java" checks="AbbreviationAsWordInName"/> <!-- evToEBITDATTM, netDebtToEBITDATTM -->
<suppress files="FmpMoney.java" checks="MagicNumber"/> <!-- zero, unit, thousand, million -->
<suppress files="FmpNumbers.java" checks="MagicNumber"/> <!-- decimal -->
<suppress files="FmpRatioTtm.java" checks="AbbreviationAsWordInName"/> <!-- netIncomePerEBTTTM -->
<suppress files="FmpSymbolTest.java" checks="IllegalCatch"/> <!-- check_all_symbols -->
</suppressions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.sorn.fmp4j.exceptions;

public class FmpInvalidMinorUnitException extends FmpException {
public FmpInvalidMinorUnitException(String message, Object... args) {
super(message, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,5 @@ public record FmpBalanceSheetStatement(
Long netDebt)
implements FmpModel, FmpStatement {
@Serial
private static final long serialVersionUID = 5L;
private static final long serialVersionUID = 6L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,5 @@ public record FmpBalanceSheetStatementGrowth(
Double growthTreasuryStock)
implements FmpModel, FmpStatement {
@Serial
private static final long serialVersionUID = 2L;
private static final long serialVersionUID = 3L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,5 @@ public record FmpCashFlowStatement(
Long interestPaid)
implements FmpModel, FmpStatement {
@Serial
private static final long serialVersionUID = 5L;
private static final long serialVersionUID = 6L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ public record FmpCashFlowStatementGrowth(
Double growthInterestPaid)
implements FmpModel, FmpStatement {
@Serial
private static final long serialVersionUID = 2L;
private static final long serialVersionUID = 3L;
}
2 changes: 1 addition & 1 deletion src/main/java/dev/sorn/fmp4j/models/FmpCompanies.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,5 @@ public record FmpCompanies(
Boolean isFund)
implements FmpModel {
@Serial
private static final long serialVersionUID = 8L;
private static final long serialVersionUID = 9L;
}
2 changes: 1 addition & 1 deletion src/main/java/dev/sorn/fmp4j/models/FmpCompany.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ public record FmpCompany(
Boolean isFund)
implements FmpModel {
@Serial
private static final long serialVersionUID = 8L;
private static final long serialVersionUID = 9L;
}
2 changes: 1 addition & 1 deletion src/main/java/dev/sorn/fmp4j/models/FmpEtfInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public record FmpEtfInfo(
List<SectorExposure> sectorsList)
implements FmpModel {
@Serial
private static final long serialVersionUID = 6L;
private static final long serialVersionUID = 7L;

// The first parameter is sector information, however FMP API wrongly returns as "industry"
// API sample return in stable/etf/info/%3Fsymbol=SPY.json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,5 @@ public record FmpFinancialGrowth(
Double threeYBottomLineNetIncomeGrowthPerShare)
implements FmpModel, FmpStatement {
@Serial
private static final long serialVersionUID = 4L;
private static final long serialVersionUID = 5L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ public record FmpIncomeStatement(
Long weightedAverageShsOutDil)
implements FmpModel, FmpStatement {
@Serial
private static final long serialVersionUID = 5L;
private static final long serialVersionUID = 6L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@ public record FmpIncomeStatementGrowth(
Double growthNetIncomeDeductions)
implements FmpModel, FmpStatement {
@Serial
private static final long serialVersionUID = 2L;
private static final long serialVersionUID = 3L;
}
2 changes: 1 addition & 1 deletion src/main/java/dev/sorn/fmp4j/models/FmpKeyMetric.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@ public record FmpKeyMetric(
Long netCurrentAssetValue)
implements FmpModel {
@Serial
private static final long serialVersionUID = 4L;
private static final long serialVersionUID = 5L;
}
2 changes: 1 addition & 1 deletion src/main/java/dev/sorn/fmp4j/models/FmpRatio.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,5 @@ public record FmpRatio(
Double dividendPerShare)
implements FmpModel {
@Serial
private static final long serialVersionUID = 4L;
private static final long serialVersionUID = 5L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ public record FmpRevenueGeographicSegmentation(
Map<String, Long> data)
implements FmpModel {
@Serial
private static final long serialVersionUID = 4L;
private static final long serialVersionUID = 5L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ public record FmpRevenueProductSegmentation(
Map<String, Long> data)
implements FmpModel {
@Serial
private static final long serialVersionUID = 4L;
private static final long serialVersionUID = 5L;
}
2 changes: 1 addition & 1 deletion src/main/java/dev/sorn/fmp4j/models/FmpSearchByCik.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ public record FmpSearchByCik(
FmpSymbol symbol, String companyName, FmpCik cik, FmpExchange exchange, FmpCurrency currency)
implements FmpModel {
@Serial
private static final long serialVersionUID = 4L;
private static final long serialVersionUID = 5L;
}
2 changes: 1 addition & 1 deletion src/main/java/dev/sorn/fmp4j/models/FmpSearchByName.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
public record FmpSearchByName(FmpSymbol symbol, String name, FmpCurrency currency, FmpExchange exchange)
implements FmpModel {
@Serial
private static final long serialVersionUID = 4L;
private static final long serialVersionUID = 5L;
}
2 changes: 1 addition & 1 deletion src/main/java/dev/sorn/fmp4j/models/FmpSearchBySymbol.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
public record FmpSearchBySymbol(FmpSymbol symbol, String name, FmpCurrency currency, FmpExchange exchange)
implements FmpModel {
@Serial
private static final long serialVersionUID = 3L;
private static final long serialVersionUID = 4L;
}
3 changes: 2 additions & 1 deletion src/main/java/dev/sorn/fmp4j/types/FmpCurrency.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
public final class FmpCurrency implements Comparable<FmpCurrency>, FmpValueObject<String> {
public static final Pattern FMP_CURRENCY_PATTERN = compile("^[A-Z]{3}$");
public static final FmpCurrency EUR = currency("EUR");
public static final FmpCurrency USD = currency("USD");

private final String value;
Expand All @@ -25,7 +26,7 @@
if (value == null) {
throw new FmpInvalidCurrencyException("'value' is required");
}
String normalized = value.toUpperCase();
final var normalized = value.toUpperCase();

Check warning on line 29 in src/main/java/dev/sorn/fmp4j/types/FmpCurrency.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/main/java/dev/sorn/fmp4j/types/FmpCurrency.java#L29

When doing a String.toLowerCase()/toUpperCase() call, use a Locale
if (!FMP_CURRENCY_PATTERN.matcher(normalized).matches()) {
throw new FmpInvalidCurrencyException(
"'value' [%s] does not match pattern [%s]", value, FMP_CURRENCY_PATTERN.pattern());
Expand Down
56 changes: 56 additions & 0 deletions src/main/java/dev/sorn/fmp4j/types/FmpMinorUnit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package dev.sorn.fmp4j.types;

import static java.lang.String.valueOf;

import dev.sorn.fmp4j.exceptions.FmpInvalidMinorUnitException;

public final class FmpMinorUnit implements FmpValueObject<Integer> {
public static final int MIN_MINOR_UNIT_VALUE = 0;
public static final int MAX_MINOR_UNIT_VALUE = 24;
private final int value;

Check warning on line 10 in src/main/java/dev/sorn/fmp4j/types/FmpMinorUnit.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/main/java/dev/sorn/fmp4j/types/FmpMinorUnit.java#L10

Field value has the same name as a method

private FmpMinorUnit(int value) {
if (value < 0) {
throw new FmpInvalidMinorUnitException(
"[%d] is below the minimum allowed value [%d]", value, MIN_MINOR_UNIT_VALUE);
}
if (value > MAX_MINOR_UNIT_VALUE) {
throw new FmpInvalidMinorUnitException(
"[%d] exceeds the maximum allowed value [%d]", value, MAX_MINOR_UNIT_VALUE);
}
this.value = value;
}

public static FmpMinorUnit minorUnit(int value) {
return new FmpMinorUnit(value);
}

@Override
public Integer value() {
return value;
}

@Override
public String toString() {
return valueOf(value);
}

@Override
public int hashCode() {
return value;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof FmpMinorUnit that)) {
return false;
}
return this.value == that.value;
}
}
129 changes: 129 additions & 0 deletions src/main/java/dev/sorn/fmp4j/types/FmpMoney.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package dev.sorn.fmp4j.types;

import static dev.sorn.fmp4j.utils.FmpNumbers.decimal;
import static java.lang.String.format;
import static java.math.BigDecimal.ZERO;
import static java.util.Objects.hash;

import java.math.BigDecimal;
import java.util.function.BiFunction;

public class FmpMoney implements Comparable<FmpMoney> {
private final FmpCurrency currency;

Check warning on line 12 in src/main/java/dev/sorn/fmp4j/types/FmpMoney.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/main/java/dev/sorn/fmp4j/types/FmpMoney.java#L12

Field currency has the same name as a method
private final BigDecimal quantity;

Check warning on line 13 in src/main/java/dev/sorn/fmp4j/types/FmpMoney.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/main/java/dev/sorn/fmp4j/types/FmpMoney.java#L13

Field quantity has the same name as a method

private FmpMoney(FmpCurrency currency, BigDecimal quantity) {
this.currency = currency;
this.quantity = quantity;
}

public static FmpMoney money(FmpCurrency currency, BigDecimal quantity) {
return new FmpMoney(currency, quantity);
}

public static FmpMoney zero(FmpCurrency currency) {
return new FmpMoney(currency, decimal(0L));
}

public static FmpMoney unit(FmpCurrency currency) {
return new FmpMoney(currency, decimal(1L));
}

public static FmpMoney thousand(FmpCurrency currency) {
return new FmpMoney(currency, decimal(1_000L));
}

public static FmpMoney million(FmpCurrency currency) {
return new FmpMoney(currency, decimal(1_000_000L));
}

public FmpCurrency currency() {
return currency;
}

public BigDecimal quantity() {
return quantity;
}

public boolean isPositive() {
return quantity.compareTo(ZERO) > 0;
}

public boolean isNegative() {
return quantity.compareTo(ZERO) < 0;
}

public boolean isZero() {
return quantity.compareTo(ZERO) == 0;
}

public FmpMoney abs() {
return new FmpMoney(currency, quantity.abs());
}

public FmpMoney neg() {
return new FmpMoney(currency, quantity.negate());
}

public FmpMoney add(FmpMoney that) {
return perform(that, "add", BigDecimal::add);
}

public FmpMoney sub(FmpMoney that) {
return perform(that, "sub", BigDecimal::subtract);
}

public FmpMoney mul(FmpMoney that) {
return perform(that, "mul", BigDecimal::multiply);
}

public FmpMoney div(FmpMoney that) {
return perform(that, "div", BigDecimal::divide);
}

public int compareTo(FmpMoney money) {
final var that = checkThat(money, "cmp");
return this.quantity.compareTo(that.quantity);
}

@Override
public String toString() {
return currency.toString() + " " + quantity;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof FmpMoney that)) {
return false;
}
if (!this.currency.equals(that.currency)) {
return false;
}
return this.quantity.compareTo(that.quantity) == 0;
}

@Override
public int hashCode() {
return hash(currency.hashCode(), quantity);
}

private FmpMoney perform(FmpMoney that, String opName, BiFunction<BigDecimal, BigDecimal, BigDecimal> op) {
final var money = checkThat(that, opName);
return new FmpMoney(currency, op.apply(this.quantity, money.quantity));
}

private FmpMoney checkThat(FmpMoney that, String opName) {
if (!this.currency.equals(that.currency)) {
throw new IllegalArgumentException(format(
"Cannot apply operation [%s] for different currencies [%s] and [%s]",
opName, this.currency, that.currency));
}
return that;
}
}
20 changes: 20 additions & 0 deletions src/main/java/dev/sorn/fmp4j/utils/FmpNumbers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.sorn.fmp4j.utils;

import static java.math.RoundingMode.HALF_EVEN;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class FmpNumbers {
public static BigDecimal decimal(double value) {
return decimal(value, 2, HALF_EVEN);
}

public static BigDecimal decimal(double value, int scale, RoundingMode mode) {
return BigDecimal.valueOf(value).setScale(scale, mode);
}

private FmpNumbers() {
// prevent direct instantiation
}
}
Loading
Loading