diff --git a/JCash.iml b/JCash.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/JCash.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..3e59c38 --- /dev/null +++ b/src/Main.java @@ -0,0 +1,5 @@ +public class Main { + public static void main(String[] args) { + System.out.println("Hello world!"); + } +} \ No newline at end of file diff --git a/src/me/teridax/jcash/banking/Account.java b/src/me/teridax/jcash/banking/Account.java new file mode 100644 index 0000000..36b534a --- /dev/null +++ b/src/me/teridax/jcash/banking/Account.java @@ -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; + } +} diff --git a/src/me/teridax/jcash/banking/Bank.java b/src/me/teridax/jcash/banking/Bank.java new file mode 100644 index 0000000..026b5d5 --- /dev/null +++ b/src/me/teridax/jcash/banking/Bank.java @@ -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 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; + } +} diff --git a/src/me/teridax/jcash/banking/BankingManagementSystem.java b/src/me/teridax/jcash/banking/BankingManagementSystem.java new file mode 100644 index 0000000..1cd09ae --- /dev/null +++ b/src/me/teridax/jcash/banking/BankingManagementSystem.java @@ -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 banks; + + private BankingManagementSystem(List banks) { + this.banks = banks; + } + + public static BankingManagementSystem loadFromCsv(File file) { + + try { + var content = Files.readString(file.toPath()); + + var banks = new ArrayList(); + + 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; + } +} diff --git a/src/me/teridax/jcash/banking/Girokonto.java b/src/me/teridax/jcash/banking/Girokonto.java new file mode 100644 index 0000000..68ba9f5 --- /dev/null +++ b/src/me/teridax/jcash/banking/Girokonto.java @@ -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; + } +} diff --git a/src/me/teridax/jcash/banking/Owner.java b/src/me/teridax/jcash/banking/Owner.java new file mode 100644 index 0000000..1f337e8 --- /dev/null +++ b/src/me/teridax/jcash/banking/Owner.java @@ -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); + } +} diff --git a/src/me/teridax/jcash/banking/SavingsAccount.java b/src/me/teridax/jcash/banking/SavingsAccount.java new file mode 100644 index 0000000..7e36c58 --- /dev/null +++ b/src/me/teridax/jcash/banking/SavingsAccount.java @@ -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; + } +} diff --git a/src/me/teridax/jcash/decode/Decoder.java b/src/me/teridax/jcash/decode/Decoder.java new file mode 100644 index 0000000..66542f1 --- /dev/null +++ b/src/me/teridax/jcash/decode/Decoder.java @@ -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"); + } +}