115 lines
4.1 KiB
Java
115 lines
4.1 KiB
Java
package me.teridax.jcash.banking;
|
|
|
|
import me.teridax.jcash.decode.StringDecoder;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.*;
|
|
|
|
/**
|
|
* Management system for banks and all accounts provided by these banks and their respective account owners.
|
|
* This class serves a read only database which can only modify runtime data without any respect to CRUD or the ACID
|
|
* principles.
|
|
*/
|
|
public final class BankingManagementSystem {
|
|
|
|
/**
|
|
* A set of banks
|
|
*/
|
|
private final Set<Bank> banks;
|
|
|
|
private BankingManagementSystem() {
|
|
this.banks = new HashSet<>();
|
|
}
|
|
|
|
/**
|
|
* Utility method for retrieving the tail of a string array.
|
|
* This method return all items which follow the n-th index denoted by index.
|
|
* @param array the array to take the tail of
|
|
* @param index the amount trailing indices to skip
|
|
* @return an array containing the last elements of the supplied array
|
|
*/
|
|
private static String[] tail(String[] array, int index) {
|
|
return Arrays.stream(array).skip(index).toArray(String[]::new);
|
|
}
|
|
|
|
/**
|
|
* Loads an instance of this class from a csv file.
|
|
* The csv file must comply to the formats of {@link StringDecoder} and must contain
|
|
* the following columns in this exact order:
|
|
* <ol>
|
|
* <li>Bank name</li>
|
|
* <li>Bank BLZ</li>
|
|
* <li>Account IBAN</li>
|
|
* <li>Account PIN</li>
|
|
* <li>Account Balance</li>
|
|
* <li>Account type</li>
|
|
* <li>Account Interest rate</li>
|
|
* <li>Account Overdraft</li>
|
|
* <li>Owner uuid</li>
|
|
* <li>Owner family name</li>
|
|
* <li>Owner name</li>
|
|
* <li>Owner street</li>
|
|
* <li>Owner plz</li>
|
|
* <li>Owner city</li>
|
|
* </ol>
|
|
* The file can contain a header line which gets skipped when reading.
|
|
* Note that the first line is always skipped and the name of every column is not checked in any way.
|
|
* @param file the file to parse
|
|
* @throws IllegalArgumentException if the file cannot be read or the containing data is invalid
|
|
* @return a valid BMS
|
|
*/
|
|
public static BankingManagementSystem loadFromCsv(Path file) throws IllegalArgumentException {
|
|
try {
|
|
var bms = new BankingManagementSystem();
|
|
var content = Files.readString(file);
|
|
|
|
// read line by line
|
|
// and skip the first line
|
|
content.lines().skip(1).forEach(line -> {
|
|
// split the line into columns
|
|
var columns = line.split(";");
|
|
|
|
// one line must contain exactly 14 columns
|
|
if (columns.length != 14)
|
|
throw new IllegalArgumentException("invalid column count: " + columns.length);
|
|
|
|
// read basic fields
|
|
var owner = Owner.fromColumns(tail(columns, 8));
|
|
var account = Account.fromColumns(tail(columns, 2));
|
|
|
|
var blz = Bank.validateBlz(columns[1]);
|
|
var name = StringDecoder.decodeName(columns[0]);
|
|
var bankOfLine = new Bank(blz, name);
|
|
|
|
// add banks to bms
|
|
|
|
var bankOfSet = bms.banks.stream().filter(b -> b.equals(bankOfLine)).findFirst();
|
|
if (bankOfSet.isPresent()) {
|
|
bankOfSet.get().addAccount(owner, account);
|
|
} else {
|
|
bankOfLine.addAccount(owner, account);
|
|
bms.banks.add(bankOfLine);
|
|
}
|
|
});
|
|
|
|
return bms;
|
|
|
|
} catch (IOException e) {
|
|
throw new IllegalArgumentException("Could not read file " + file, e);
|
|
} catch (IllegalArgumentException | NullPointerException e) {
|
|
throw new IllegalArgumentException("Could not parse file " + file, e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return a bank with the given blz.
|
|
* @param blz the blz to search bank of
|
|
* @return the bank with this blz or none
|
|
*/
|
|
public Optional<Bank> getBank(String blz) {
|
|
return this.banks.stream().filter(b -> b.getBlz().equals(blz)).findFirst();
|
|
}
|
|
}
|