Commit 7844c04c by Patryk Czarnik

Przykład Waluty - dodanie do głównego projektu

parent 817147f8
......@@ -12,4 +12,17 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.json</artifactId>
<version>2.0.1</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package gotowe.p40_io;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
public class Download_HttpClient {
public static void main(String[] args) {
final String ADRES = "http://api.nbp.pl/api/exchangerates/tables/a/";
try {
System.out.println("Startujemy...");
URI uri = new URI(ADRES);
HttpClient httpClient = HttpClient.newHttpClient();
System.out.println("Mam klienta: " + httpClient);
System.out.println("Wysyłam zapytanie...");
HttpRequest request = HttpRequest.newBuilder(uri).build();
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());
System.out.println("Mam odpowiedź: " + response);
System.out.println("Kod: " + response.statusCode());
System.out.println("Content-Type: " + response.headers().firstValue("Content-Type").orElse("--nieokreślony--"));
String body = response.body();
System.out.println("Rozmiar treści: " + body.length());
System.out.println(body.substring(0, 80));
System.out.println("Gotowe.");
} catch(Exception e) {
e.printStackTrace();
}
}
}
......@@ -8,7 +8,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
public class Download {
public class Download_URL {
public static void main(String[] args) {
try {
......
package waluty;
public class BladAplikacji extends Exception {
public BladAplikacji() {
super();
}
public BladAplikacji(String message) {
super(message);
}
public BladAplikacji(String message, Throwable cause) {
super(message, cause);
}
}
package waluty;
import java.time.LocalDate;
public abstract class Pobieranie {
protected static final String ADRES_BAZOWY = "http://api.nbp.pl/api/exchangerates/tables";
public abstract Tabela pobierzBiezaceKursy() throws BladAplikacji;
public abstract Tabela pobierzArchiwalneKursy(String data) throws BladAplikacji;
// Jeśli jakaś część implementacji jest wpólna dla wszystkich podklas,
// to można umieścić ja w klasie abstrakcyjnej
public Tabela pobierzArchiwalneKursy(LocalDate data) throws BladAplikacji {
return pobierzArchiwalneKursy(data.toString());
}
// fabryka nowych obiektów
public static Pobieranie utworz(String format) {
return switch(format.toUpperCase()) {
case "XML" -> new PobieranieXML();
case "JSON" -> new PobieranieJSON();
default -> throw new IllegalArgumentException("Nieznany format " + format);
};
}
}
package waluty;
import java.io.InputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.time.LocalDate;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonReader;
import jakarta.json.JsonValue;
public class PobieranieJSON extends Pobieranie {
private HttpClient httpClient = HttpClient.newHttpClient();
@Override
public Tabela pobierzBiezaceKursy() throws BladAplikacji {
return pobierzZAdresu(ADRES_BAZOWY + "/A" + "?format=json");
}
@Override
public Tabela pobierzArchiwalneKursy(String data) throws BladAplikacji {
return pobierzZAdresu(ADRES_BAZOWY + "/A/" + data + "?format=json");
}
private Tabela pobierzZAdresu(String adres) throws BladAplikacji {
try {
URI uri = new URI(adres);
HttpRequest request = HttpRequest.newBuilder(uri).build();
HttpResponse<InputStream> response = httpClient.send(request, BodyHandlers.ofInputStream());
if(response.statusCode() != 200) {
throw new BladAplikacji("Brak danych w odpowiedzi HTTP, kod " + response.statusCode());
}
return tabelaZJSON(response.body());
} catch(BladAplikacji e) {
throw e;
} catch(Exception e) {
throw new BladAplikacji("Błąd podczas pobierania XML: " + e.getMessage(), e);
}
}
private Tabela tabelaZJSON(InputStream input) {
try(JsonReader reader = Json.createReader(input)) {
// dokument zawiera [tablicę], a ta tablica zawiera {obiekt}
JsonArray array = reader.readArray();
JsonObject tabela = array.getJsonObject(0);
// String typ = tabela.getString("table");
String no = tabela.getString("no");
LocalDate date = LocalDate.parse(tabela.getString("effectiveDate"));
Tabela wynikowaTabela = new Tabela(no, date);
JsonArray rates = tabela.getJsonArray("rates");
for(JsonValue jsonValue : rates) {
JsonObject jsonObject = jsonValue.asJsonObject();
Waluta waluta = new Waluta(jsonObject.getString("code"),
jsonObject.getString("currency"),
jsonObject.getJsonNumber("mid").bigDecimalValue());
wynikowaTabela.addRate(waluta);
}
return wynikowaTabela;
}
}
}
package waluty;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class PobieranieXML extends Pobieranie {
private HttpClient httpClient = HttpClient.newHttpClient();
private DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
private XPathFactory xpf = XPathFactory.newInstance();
@Override
public Tabela pobierzBiezaceKursy() throws BladAplikacji {
return pobierzZAdresu(ADRES_BAZOWY + "/A" + "?format=xml");
}
@Override
public Tabela pobierzArchiwalneKursy(String data) throws BladAplikacji {
return pobierzZAdresu(ADRES_BAZOWY + "/A/" + data + "?format=xml");
}
private Tabela pobierzZAdresu(String adres) throws BladAplikacji {
try {
URI uri = new URI(adres);
HttpRequest request = HttpRequest.newBuilder(uri).build();
HttpResponse<InputStream> response = httpClient.send(request, BodyHandlers.ofInputStream());
if(response.statusCode() != 200) {
throw new BladAplikacji("Brak danych w odpowiedzi HTTP, kod " + response.statusCode());
}
DocumentBuilder builder = dbf.newDocumentBuilder();
Document document = builder.parse(response.body());
return tabelaZXML(document);
} catch(BladAplikacji e) {
throw e;
} catch(Exception e) {
throw new BladAplikacji("Błąd podczas pobierania XML: " + e.getMessage(), e);
}
}
private Tabela tabelaZXML(Document document) throws XPathExpressionException {
XPath xpath = xpf.newXPath();
// String no = xpath.evaluate("/ArrayOfExchangeRatesTable/ExchangeRatesTable/No", document);
// String date = xpath.evaluate("/ArrayOfExchangeRatesTable/ExchangeRatesTable/EffectiveDate", document);
String no = xpath.evaluate("//No", document);
String date = xpath.evaluate("//EffectiveDate", document);
Tabela tabela = new Tabela(no, date);
NodeList rates = (NodeList) xpath.evaluate("//Rate", document, XPathConstants.NODESET);
final int length = rates.getLength();
for(int i = 0; i < length; i++) {
Node rate = rates.item(i);
String currency = xpath.evaluate("Currency", rate);
String code = xpath.evaluate("Code", rate);
BigDecimal mid = new BigDecimal(xpath.evaluate("Mid", rate));
Waluta waluta = new Waluta(code, currency, mid);
tabela.addRate(waluta);
}
return tabela;
}
}
package waluty;
import java.math.BigDecimal;
import java.util.Locale;
import java.util.Optional;
import java.util.Scanner;
public class PrzelicznikKonsolowy {
private Scanner scanner;
private Pobieranie pobieranie;
public PrzelicznikKonsolowy() {
scanner = new Scanner(System.in);
scanner.useLocale(Locale.US);
}
public static void main(String[] args) {
new PrzelicznikKonsolowy().run();
}
public void run() {
System.out.println("Wybierz format danych: XML / JSON");
String format = scanner.nextLine().trim().toUpperCase();
switch(format) {
case "XML" -> pobieranie = new PobieranieXML();
case "", "JSON" -> pobieranie = new PobieranieJSON();
default -> {
System.out.println("Nieznany format, kończę program.");
return;
}
}
program: while(true) {
System.out.println("\nWpisz datę w formacie YYYY-MM-DD lub naciśnij ENTER, aby pobrać bieżące kursy.");
System.out.println("Możesz też wpisać Q , aby zakończyć program");
String data = scanner.nextLine();
try {
Tabela tabela;
switch(data) {
case "q", "Q" -> {break program;}
case "" -> tabela = pobieranie.pobierzBiezaceKursy();
default -> tabela = pobieranie.pobierzArchiwalneKursy(data);
}
dzialajDlaWybranejTabeli(tabela);
} catch(BladAplikacji e) {
System.out.println("Wyjątek! " + e.getMessage());
}
}
System.out.println("Koniec programu");
}
private void dzialajDlaWybranejTabeli(Tabela tabela) {
System.out.println(tabela);
while(true) {
System.out.println("\nPodaj kod waluty, lub Q aby zakończyć pracę z bieżącą tabelą");
String code = scanner.nextLine().toUpperCase();
if("Q".equals(code)) {
break;
}
Optional<Waluta> found = tabela.findByCode(code);
if(found.isEmpty()) {
System.out.println("Nie ma waluty o kodzie " + code);
continue;
}
dzialajDlaWybranejWaluty(found.get());
}
}
private void dzialajDlaWybranejWaluty(Waluta waluta) {
System.out.println("Wybrana waluta: " + waluta.code() + " (" + waluta.currency() + ")" + ", kurs " + waluta.mid());
while(true) {
System.out.println("\nPodaj kwotę do przeliczenia. 0 oznacza koniec:");
BigDecimal kwota = scanner.nextBigDecimal();
scanner.nextLine();
if(kwota.compareTo(BigDecimal.ZERO) == 0) {
break;
}
BigDecimal wynikWaluta = waluta.przeliczNaWalute(kwota);
BigDecimal wynikPLN = waluta.przeliczNaZlote(kwota);
System.out.println(kwota + " " + waluta.code() + " = " + wynikPLN + " PLN");
System.out.println(kwota + " PLN = " + wynikWaluta + " " + waluta.code());
}
}
}
package waluty;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class Tabela {
private final String no;
private final LocalDate effectiveDate;
private final List<Waluta> rates = new ArrayList<>();
public Tabela(String no, LocalDate effectiveDate) {
this.no = no;
this.effectiveDate = effectiveDate;
}
public Tabela(String no, String effectiveDate) {
this(no, LocalDate.parse(effectiveDate));
}
public void addRate(Waluta waluta) {
rates.add(waluta);
}
public String no() {
return no;
}
public LocalDate effectiveDate() {
return effectiveDate;
}
public List<Waluta> rates() {
// dostęp tylko do odczytu
return Collections.unmodifiableList(rates);
}
@Override
public String toString() {
return "Tabela nr " + no + " z dnia " + effectiveDate + ", " + rates.size() + " walut";
}
public Optional<Waluta> findByCode(String code) {
for(Waluta waluta : rates) {
if(waluta.code().equals(code) ) {
return Optional.of(waluta);
}
}
return Optional.empty();
}
public String[] codes() {
return rates.stream().map(Waluta::code).toArray(String[]::new);
}
}
package waluty;
import java.math.BigDecimal;
import java.math.RoundingMode;
public record Waluta(
String code,
String currency,
BigDecimal mid) {
public BigDecimal przeliczNaZlote(BigDecimal kwota) {
return kwota.multiply(mid).setScale(2, RoundingMode.HALF_EVEN);
}
public BigDecimal przeliczNaWalute(BigDecimal kwota) {
// Już do operacji dzielenia przekazujemy informację o oczekiwanej precyzji i sposobie zaokrąglenia.
return kwota.divide(mid, 2, RoundingMode.HALF_EVEN);
}
}
package waluty;
public class WypiszWalutyJSON {
public static void main(String[] args) {
System.out.println("Startujemy...");
PobieranieJSON pobieranie = new PobieranieJSON();
try {
Tabela tabela = pobieranie.pobierzBiezaceKursy();
System.out.println("Udało się pobrać tabelę");
System.out.println(tabela);
System.out.println();
for(Waluta waluta : tabela.rates()) {
System.out.println(waluta);
}
} catch(BladAplikacji e) {
e.printStackTrace();
}
}
}
package waluty;
public class WypiszWalutyXML {
public static void main(String[] args) {
System.out.println("Startujemy...");
PobieranieXML pobieranie = new PobieranieXML();
try {
Tabela tabela = pobieranie.pobierzBiezaceKursy();
System.out.println("Udało się pobrać tabelę");
System.out.println(tabela);
System.out.println();
for(Waluta waluta : tabela.rates()) {
System.out.println(waluta);
}
} catch(BladAplikacji e) {
e.printStackTrace();
}
}
}
package waluty;
import static org.junit.jupiter.api.Assertions.*;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;
class WalutaTest {
// arrange - act - assert
// having - when - then
@Test
void testTworzeniaObiektu() {
BigDecimal kurs = new BigDecimal("4.0123");
Waluta waluta = new Waluta("USD", "dolar", kurs);
// assert "USD".equals(waluta.code());
// JUnit oferuje własne asercje w postaci metod:
assertEquals("USD", waluta.code());
assertEquals("dolar", waluta.currency());
assertEquals(kurs, waluta.mid());
}
@Test
void testPrzeliczNaZlote() {
// Ze względu na to, że pracujemy z BigDecimal, wcześniej przygotowuję wartości używane w teście i zapisuję do zmiennych
BigDecimal kurs = new BigDecimal("4.0000");
BigDecimal kwota = new BigDecimal("1000.00");
BigDecimal oczekiwanyWynik = new BigDecimal("4000.00");
Waluta waluta = new Waluta("USD", "dolar", kurs);
BigDecimal wynik = waluta.przeliczNaZlote(kwota);
assertEquals(oczekiwanyWynik, wynik);
}
@Test
void testPrzeliczNaZloteZaokrlaglanie() {
BigDecimal kurs = new BigDecimal("3.3333");
BigDecimal kwota = new BigDecimal("20.00");
BigDecimal oczekiwanyWynik = new BigDecimal("66.67");
Waluta waluta = new Waluta("ABC", "cośtam", kurs);
BigDecimal wynik = waluta.przeliczNaZlote(kwota);
assertEquals(oczekiwanyWynik, wynik);
}
@Test
void testPrzeliczNaWalute() {
BigDecimal kurs = new BigDecimal("4.0000");
BigDecimal kwota = new BigDecimal("4000.00");
BigDecimal oczekiwanyWynik = new BigDecimal("1000.00");
Waluta waluta = new Waluta("USD", "dolar", kurs);
BigDecimal wynik = waluta.przeliczNaWalute(kwota);
assertEquals(oczekiwanyWynik, wynik);
}
@Test
void testPrzeliczNaWaluteZaokrlaglanie() {
BigDecimal kurs = new BigDecimal("3.0000");
BigDecimal kwota = new BigDecimal("2000.00");
BigDecimal oczekiwanyWynik = new BigDecimal("666.67");
Waluta waluta = new Waluta("XYZ", "dolar iksowy", kurs);
BigDecimal wynik = waluta.przeliczNaWalute(kwota);
assertEquals(oczekiwanyWynik, wynik);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment