added data classes

This commit is contained in:
Sven Vogel 2023-06-22 10:27:44 +02:00
parent 06b7666aa3
commit ec23a2b32f
9 changed files with 361 additions and 0 deletions

11
JCash.iml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

5
src/Main.java Normal file
View File

@ -0,0 +1,5 @@
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}

View File

@ -0,0 +1,34 @@
package me.teridax.jcash.banking;
@SuppressWarnings("unused")
public abstract class Account {
private int iban;
private int pin;
private double balance;
private final Owner owner;
public Account(int iban, int pin, Owner owner) {
this.owner = owner;
this.iban = iban;
this.pin = pin;
this.balance = 0.0d;
}
public Owner getOwner() {
return owner;
}
public int getIban() {
return iban;
}
public int getPin() {
return pin;
}
public double getBalance() {
return balance;
}
}

View File

@ -0,0 +1,61 @@
package me.teridax.jcash.banking;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@SuppressWarnings("unused")
public final class Bank {
private String name;
private int blz;
private List<Account> accounts;
private Bank(int blz, String name) {
this.blz = blz;
this.name = name;
this.accounts = new ArrayList<>();
}
public Account[] getAccounts() {
return accounts.toArray(new Account[0]);
}
public int getBlz() {
return blz;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Bank) {
return blz == ((Bank) obj).blz;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(blz, name);
}
public Account[] getAccountsOfOwner(Owner owner) {
return accounts.stream()
.filter(account -> account.getOwner().equals(owner))
.toArray(Account[]::new);
}
private static String validateBlz(String maybeBlz) {
var builder = new StringBuilder();
maybeBlz.trim().chars().filter(ch -> Character.isDigit(ch) || Character.isLetter(ch)).forEach(builder::append);
var blz = builder.toString();
if (blz.isEmpty()) {
throw new IllegalArgumentException("Bank Blz must only contain letters and digits");
}
return blz;
}
}

View File

@ -0,0 +1,35 @@
package me.teridax.jcash.banking;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
public final class BankingManagementSystem {
private List<Bank> banks;
private BankingManagementSystem(List<Bank> banks) {
this.banks = banks;
}
public static BankingManagementSystem loadFromCsv(File file) {
try {
var content = Files.readString(file.toPath());
var banks = new ArrayList<Bank>();
content.lines().forEach(line -> {
// load bank and account from line.
// transfer accounts to existing bank if already created
});
} catch (IOException e) {
throw new IllegalArgumentException("Could not read file " + file);
}
return null;
}
}

View File

@ -0,0 +1,15 @@
package me.teridax.jcash.banking;
public class Girokonto extends Account {
private double overdraft;
public Girokonto(int iban, int pin, double overdraft, Owner owner) {
super(iban, pin, owner);
this.overdraft = overdraft;
}
public double getOverdraft() {
return overdraft;
}
}

View File

@ -0,0 +1,66 @@
package me.teridax.jcash.banking;
import java.util.Objects;
@SuppressWarnings("unused")
public final class Owner {
private int uid;
private String familyName;
private String name;
private String street;
private int zip;
private String city;
private Owner() { }
public Owner(int uid, String familyName, String name, int zip, String city, String street) {
this.uid = uid;
this.familyName = familyName;
this.name = name;
this.zip = zip;
this.city = city;
this.street = street;
}
public long getUid() {
return uid;
}
public String getFamilyName() {
return familyName;
}
public String getName() {
return name;
}
public int getZip() {
return zip;
}
public String getCity() {
return city;
}
public String getStreet() {
return street;
}
@Override
public int hashCode() {
return Objects.hash(uid, familyName, name, zip, city, street);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Owner) {
return this.uid == ((Owner) obj).getUid();
}
return false;
}
@Override
public String toString() {
return String.format("@Owner[uid=%08x, familyName=%s, name=%s, zip=%s, city=%s, street=%s]", uid, familyName, name, zip, city, street);
}
}

View File

@ -0,0 +1,16 @@
package me.teridax.jcash.banking;
@SuppressWarnings("unused")
public class SavingsAccount extends Account {
private double interest;
public SavingsAccount(int iban, int pin, double interest, Owner owner) {
super(iban, pin, owner);
this.interest = interest;
}
public double getInterest() {
return interest;
}
}

View File

@ -0,0 +1,118 @@
package me.teridax.jcash.decode;
import org.junit.Test;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Pattern;
import static junit.framework.TestCase.assertEquals;
public class Decoder {
private static final Locale LOCALE = Locale.GERMANY;
private static final NumberFormat LOCAL_NUMBER_FORMAT = NumberFormat.getInstance(LOCALE);
public static double decodePercent(String number) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(number);
// trim the number and cut out optional percent symbols
var trimmed = number.trim().replace("%", "");
try {
return LOCAL_NUMBER_FORMAT.parse(trimmed).doubleValue();
} catch (ParseException ex) {
throw new IllegalArgumentException("Not a valid number: " + number, ex);
}
}
public static double decodeCurrency(String currency) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(currency);
try {
return LOCAL_NUMBER_FORMAT.parse(currency.trim()).doubleValue();
} catch (ParseException ex) {
throw new IllegalArgumentException("Not a valid currency in german locale: " + currency, ex);
}
}
public static int decodeSerialNumber(String number) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(number);
// check if the string is a valid unsigned number
try {
LOCAL_NUMBER_FORMAT.setParseIntegerOnly(true);
var serialNumber = LOCAL_NUMBER_FORMAT.parse(number.trim());
LOCAL_NUMBER_FORMAT.setParseIntegerOnly(false);
return serialNumber.intValue();
} catch (ParseException ex) {
throw new IllegalArgumentException("Not a valid serial number: " + number, ex);
}
}
public static String decodeName(String name) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(name);
var trimmed = name.trim();
// check if the string is a valid unsigned number
if (!trimmed.trim().chars().allMatch(Character::isLetter))
throw new IllegalArgumentException("Not a valid name: " + name);
return trimmed;
}
public static String decodeStreet(String street) throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(street);
var pattern = Pattern.compile("\\S+(\\s+\\d+(/\\d+)?)?", Pattern.CASE_INSENSITIVE);
var matcher = pattern.matcher(street);
if (matcher.find()) {
return matcher.group();
} else {
throw new IllegalArgumentException("not a void address");
}
}
@Test
public void testDecodeSuccessfulFunctions() {
decodeSerialNumber("95786978625347895");
decodeSerialNumber(" 927856347 ");
decodeSerialNumber("0");
decodeName("Adolf");
decodeName("Günther");
decodeName("Saßkia");
decodeStreet("Bahnhofstraße 40/1");
decodeStreet("Gülleweg 9");
decodeStreet("Echsengaße 67 / 4");
assertEquals(decodePercent("1,4%"), 1.4d);
assertEquals(decodePercent("99"), 99.0d);
assertEquals(decodePercent("1,003 %"), 1.003d);
assertEquals(decodeCurrency("1,3€"), 1.3d);
assertEquals(decodeCurrency("145,34"), 145,34d);
assertEquals(decodeCurrency("0,45 €"), 0.45d);
}
@Test(expected = IllegalArgumentException.class)
public void testDecodeInvalidFunctions() {
decodeSerialNumber("q0948tvb6q047t 740 t74z0tz 784");
decodeSerialNumber("-39867.8475");
decodeSerialNumber("-398678475");
decodeSerialNumber(" ß9qu908t76q34798t6q734vb9843");
decodeName("John Doe");
decodeName("3490qt67v 0b34");
decodeName("Alexander9");
decodeName("-ga76re78g6$§");
decodeStreet("Bahnhofstraße -40/1");
decodeStreet("Gülleweg 9//567");
decodeStreet("23Echsengaße 67 / 4 Hofwetg 9");
}
}