Commit 5029c421 by Patryk Czarnik

Aplikacja "waluty"

parent 94c047cc
...@@ -27,6 +27,12 @@ ...@@ -27,6 +27,12 @@
<version>3.49.1.0</version> <version>3.49.1.0</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>jakarta.json</artifactId>
<version>1.1.7</version>
<!-- starsza wersja: org.glassfish:jakarta.json:2.0.1 -->
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
...@@ -28,7 +28,7 @@ public class P07_GenerowaneId { ...@@ -28,7 +28,7 @@ public class P07_GenerowaneId {
try(Connection c = DriverManager.getConnection(Ustawienia.URL, Ustawienia.USER, Ustawienia.PASSWD); try(Connection c = DriverManager.getConnection(Ustawienia.URL, Ustawienia.USER, Ustawienia.PASSWD);
PreparedStatement stmt = c.prepareStatement(sql, polaGenerowane)) { PreparedStatement stmt = c.prepareStatement(sql, polaGenerowane)) {
stmt.setString(1, "Nowa z " + LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:SS"))); stmt.setString(1, "Nowa z " + LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
stmt.setString(2, "01-321"); stmt.setString(2, "01-321");
stmt.setString(3, "Warszawa"); stmt.setString(3, "Warszawa");
stmt.setString(4, "US"); stmt.setString(4, "US");
......
...@@ -13,10 +13,8 @@ public class P08a_ModyfikacjaPoprzezWynik { ...@@ -13,10 +13,8 @@ public class P08a_ModyfikacjaPoprzezWynik {
final String sql = "SELECT * FROM departments WHERE department_id < ? ORDER BY department_id"; final String sql = "SELECT * FROM departments WHERE department_id < ? ORDER BY department_id";
try(Connection c = DriverManager.getConnection(Ustawienia.URL, Ustawienia.USER, Ustawienia.PASSWD)) { try(Connection c = DriverManager.getConnection(Ustawienia.URL, Ustawienia.USER, Ustawienia.PASSWD)) {
try(PreparedStatement stmt = c.prepareStatement(sql, try(PreparedStatement stmt = c.prepareStatement(sql,
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) { ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE)) {
stmt.setInt(1, limit); stmt.setInt(1, limit);
try(ResultSet rs = stmt.executeQuery()) { try(ResultSet rs = stmt.executeQuery()) {
System.out.println("Nazwa kursora: " + rs.getCursorName()); System.out.println("Nazwa kursora: " + rs.getCursorName());
......
...@@ -63,7 +63,6 @@ public class P09_DowolnaKolejnoscResultSet { ...@@ -63,7 +63,6 @@ public class P09_DowolnaKolejnoscResultSet {
nazwisko = rs.getString(3); nazwisko = rs.getString(3);
System.out.printf(" ... a następny ma na nazwisko %s\n", nazwisko); System.out.printf(" ... a następny ma na nazwisko %s\n", nazwisko);
} }
} else { } else {
System.out.printf("\npoz %3d - nie ma takiej pozycji\n", poz); System.out.printf("\npoz %3d - nie ma takiej pozycji\n", poz);
} }
......
...@@ -19,6 +19,7 @@ public class P11_Metadane { ...@@ -19,6 +19,7 @@ public class P11_Metadane {
System.out.println(dbMetaData.getDatabaseProductName()); System.out.println(dbMetaData.getDatabaseProductName());
System.out.println(dbMetaData.getDatabaseMajorVersion() System.out.println(dbMetaData.getDatabaseMajorVersion()
+ "." + dbMetaData.getDatabaseMinorVersion()); + "." + dbMetaData.getDatabaseMinorVersion());
System.out.printf("maxStatements: " + dbMetaData.getMaxStatements());
System.out.println(); System.out.println();
try(ResultSet tables = dbMetaData.getTables(null, "public", null, null)) { try(ResultSet tables = dbMetaData.getTables(null, "public", null, null)) {
......
...@@ -12,10 +12,11 @@ public class P12_MultiResult { ...@@ -12,10 +12,11 @@ public class P12_MultiResult {
try (Connection c = DriverManager.getConnection(Ustawienia.URL, Ustawienia.USER, Ustawienia.PASSWD)) { try (Connection c = DriverManager.getConnection(Ustawienia.URL, Ustawienia.USER, Ustawienia.PASSWD)) {
try (Statement stmt = c.createStatement()) { try (Statement stmt = c.createStatement()) {
// Kilka zapytań w jednym stringu // Kilka zapytań w jednym stringu
String sql = "SELECT * FROM countries;" String sql = """
+ " SELECT * FROM jobs;" SELECT * FROM countries;
+ " SELECT first_name, last_name FROM employees"; SELECT * FROM jobs;"
SELECT first_name, last_name FROM employees
""";
if(stmt.execute(sql)) // jeśli jest pierwszy ResultSet if(stmt.execute(sql)) // jeśli jest pierwszy ResultSet
do { do {
try (ResultSet rs = stmt.getResultSet()) { try (ResultSet rs = stmt.getResultSet()) {
......
...@@ -12,7 +12,7 @@ public class P13a_Blob_Create { ...@@ -12,7 +12,7 @@ public class P13a_Blob_Create {
public static void main(String[] args) { public static void main(String[] args) {
final String sql = """ final String sql = """
DROP TABLE IF EXISTS photos; DROP TABLE IF EXISTS photos;
CREATE TABLE photos( CREATE TABLE photos(
photo_id SERIAL PRIMARY KEY, photo_id SERIAL PRIMARY KEY,
file_name VARCHAR(60) NOT NULL, file_name VARCHAR(60) NOT NULL,
......
package waluty;
public class BladAplikacji extends Exception {
public BladAplikacji() {
super();
}
public BladAplikacji(String message, Throwable cause) {
super(message, cause);
}
public BladAplikacji(String message) {
super(message);
}
public BladAplikacji(Throwable cause) {
super(cause);
}
}
package waluty;
public class DrukujWaluty {
public static void main(String[] args) {
// Pobieranie pobieranie = new PobieranieXML();
Pobieranie pobieranie = new PobieranieJSON();
// Pobieranie pobieranie = Pobieranie.utworz("XML");
// Pobieranie pobieranie = Pobieranie.utworz("JSON");
try {
TabelaWalut tabelaWalut = pobieranie.pobierzBiezaceKursy();
System.out.println(tabelaWalut);
for(Waluta waluta : tabelaWalut.getRates()) {
System.out.println(waluta);
}
} catch (BladAplikacji e) {
e.printStackTrace();
}
}
}
package waluty;
import java.time.LocalDate;
public abstract class Pobieranie {
protected static final String ADRES_BAZOWY = "https://api.nbp.pl/api/exchangerates/tables";
public abstract TabelaWalut pobierzBiezaceKursy() throws BladAplikacji;
public abstract TabelaWalut 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 TabelaWalut 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.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
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 {
public TabelaWalut pobierzBiezaceKursy() throws BladAplikacji {
String adres = ADRES_BAZOWY + "/A?format=json";
return pobierzZAdresu(adres);
}
public TabelaWalut pobierzArchiwalneKursy(String data) throws BladAplikacji {
return pobierzZAdresu(ADRES_BAZOWY + "/A/" + data + "?format=json");
}
private TabelaWalut pobierzZAdresu(String adres) throws BladAplikacji {
try(HttpClient httpClient = HttpClient.newHttpClient()) {
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("Zapytanie HTTP zwróciło " + response.statusCode());
}
// dane odebrane z sieci "parsujemy" jako JSON
try(JsonReader reader = Json.createReader(response.body())) {
JsonArray array = reader.readArray();
JsonObject tabela = array.getJsonObject(0);
String no = tabela.getString("no");
LocalDate effectiveDate = LocalDate.parse(tabela.getString("effectiveDate"));
TabelaWalut tabelaWalut = new TabelaWalut(no, effectiveDate);
JsonArray rates = tabela.getJsonArray("rates");
for(JsonValue rate : rates) {
JsonObject rateObj = rate.asJsonObject();
Waluta waluta = new Waluta(rateObj.getString("code"),
rateObj.getString("currency"),
rateObj.getJsonNumber("mid").bigDecimalValue());
tabelaWalut.addRate(waluta);
}
return tabelaWalut;
}
} catch (URISyntaxException | IOException | InterruptedException e) {
throw new BladAplikacji(e);
}
}
}
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 TabelaWalut pobierzBiezaceKursy() throws BladAplikacji {
return pobierzZAdresu(ADRES_BAZOWY + "/A" + "?format=xml");
}
@Override
public TabelaWalut pobierzArchiwalneKursy(String data) throws BladAplikacji {
return pobierzZAdresu(ADRES_BAZOWY + "/A/" + data + "?format=xml");
}
private TabelaWalut 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 TabelaWalut 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);
TabelaWalut tabela = new TabelaWalut(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 {
TabelaWalut 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(TabelaWalut 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.getCode() + " (" + waluta.getCurrency() + ")" + ", kurs " + waluta.getMid());
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.getCode() + " = " + wynikPLN + " PLN");
System.out.println(kwota + " PLN = " + wynikWaluta + " " + waluta.getCode());
}
}
}
package waluty;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Optional;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class PrzelicznikWalutOkno {
private static final Font FONT_LABEL = new Font("Times New Roman", Font.PLAIN, 24);
private static final Font FONT_WARTOSC = new Font("Dialog", Font.BOLD, 24);
private static final Font FONT_TXT = new Font("Dialog", Font.BOLD, 32);
private static final Font FONT_WYNIK = new Font("Dialog", Font.BOLD, 32);
private static final Font FONT_BUTTON = new Font("Dialog", Font.BOLD, 28);
private TabelaWalut tabela = null;
private JFrame frmPrzelicznikWalut;
private JTextField txtKwota;
private JComboBox<String> comboBox_Waluta;
private JLabel lbl_KodWaluty;
private JLabel lbl_NazwaWaluty;
private JLabel lbl_KursWaluty;
private JRadioButton rdbtnWalutaNaZlote;
private JRadioButton rdbtnZloteNaWalute;
private JButton btnPrzelicz;
private JLabel lblPrawdziwyWynik;
private final ButtonGroup buttonGroup = new ButtonGroup();
private JPanel panel_1;
private JLabel lblTabela;
private JLabel lbl_NumerTabeli;
private JLabel lblData;
private JLabel lbl_DataTabeli;
private JTextField txtData;
private JButton btnPobierzAktualne;
private Pobieranie pobieranie = Pobieranie.utworz("xml");
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
// com.formdev.flatlaf.FlatDarkLaf.setup();
PrzelicznikWalutOkno window = new PrzelicznikWalutOkno();
window.txtData.setText(LocalDate.now().toString());
window.frmPrzelicznikWalut.setVisible(true);
window.pobierzAktualneKursy();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public PrzelicznikWalutOkno() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frmPrzelicznikWalut = new JFrame();
frmPrzelicznikWalut.setTitle("Przelicznik Walut");
frmPrzelicznikWalut.setBounds(100, 100, 480, 701);
frmPrzelicznikWalut.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lblWybierzWalut = new JLabel("Wybierz walutę");
lblWybierzWalut.setFont(FONT_LABEL);
comboBox_Waluta = new JComboBox<>();
comboBox_Waluta.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
wyswietlDaneWaluty();
}
});
comboBox_Waluta.setModel(
new DefaultComboBoxModel<>(new String[] {"--"}));
comboBox_Waluta.setFont(FONT_WARTOSC);
JPanel panel = new JPanel();
txtKwota = new JTextField();
txtKwota.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
przelicz();
}
});
txtKwota.setText("100");
txtKwota.setColumns(10);
txtKwota.setFont(FONT_TXT);
JLabel lblPodajKwot = new JLabel("Podaj kwotę");
lblPodajKwot.setFont(FONT_LABEL);
rdbtnWalutaNaZlote = new JRadioButton("waluta na złote");
rdbtnWalutaNaZlote.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
przelicz();
}
});
rdbtnWalutaNaZlote.setFont(FONT_LABEL);
buttonGroup.add(rdbtnWalutaNaZlote);
rdbtnZloteNaWalute = new JRadioButton("złote na walute");
rdbtnZloteNaWalute.setFont(FONT_LABEL);
rdbtnZloteNaWalute.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
przelicz();
}
});
buttonGroup.add(rdbtnZloteNaWalute);
btnPrzelicz = new JButton("Przelicz");
btnPrzelicz.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
przelicz();
}
});
btnPrzelicz.setFont(FONT_BUTTON);
JLabel lblWynik = new JLabel("Wynik");
lblWynik.setFont(FONT_LABEL);
lblPrawdziwyWynik = new JLabel("0.00");
lblPrawdziwyWynik.setFont(FONT_WYNIK);
lblPrawdziwyWynik.setForeground(Color.GRAY);
panel_1 = new JPanel();
JLabel lblPodajDat = new JLabel("Podaj datę");
lblPodajDat.setFont(FONT_LABEL);
txtData = new JTextField();
txtData.setHorizontalAlignment(SwingConstants.CENTER);
txtData.setFont(new Font("Dialog", Font.PLAIN, 20));
txtData.setText("data");
txtData.setColumns(10);
JButton btnZmieDat = new JButton("Zmień datę");
btnZmieDat.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pobierzKursyDlaDaty();
}
});
btnZmieDat.setFont(new Font("Dialog", Font.BOLD, 18));
btnPobierzAktualne = new JButton("Pobierz aktualne");
btnPobierzAktualne.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pobierzAktualneKursy();
}
});
btnPobierzAktualne.setFont(new Font("Dialog", Font.BOLD, 18));
GroupLayout groupLayout = new GroupLayout(frmPrzelicznikWalut.getContentPane());
groupLayout.setHorizontalGroup(
groupLayout.createParallelGroup(Alignment.LEADING)
.addGroup(groupLayout.createSequentialGroup()
.addContainerGap()
.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
.addComponent(panel_1, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 448, Short.MAX_VALUE)
.addComponent(btnPrzelicz, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 448, Short.MAX_VALUE)
.addGroup(Alignment.LEADING, groupLayout.createSequentialGroup()
.addComponent(rdbtnWalutaNaZlote)
.addPreferredGap(ComponentPlacement.RELATED, 108, Short.MAX_VALUE)
.addComponent(rdbtnZloteNaWalute))
.addGroup(Alignment.LEADING, groupLayout.createSequentialGroup()
.addComponent(lblPodajKwot)
.addPreferredGap(ComponentPlacement.RELATED, 139, Short.MAX_VALUE)
.addComponent(txtKwota, GroupLayout.PREFERRED_SIZE, 189, GroupLayout.PREFERRED_SIZE))
.addComponent(panel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 448, Short.MAX_VALUE)
.addComponent(lblWynik, Alignment.LEADING)
.addComponent(lblPrawdziwyWynik, Alignment.LEADING)
.addGroup(Alignment.LEADING, groupLayout.createSequentialGroup()
.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING, false)
.addComponent(lblPodajDat, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblWybierzWalut, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 223, Short.MAX_VALUE))
.addPreferredGap(ComponentPlacement.UNRELATED)
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
.addComponent(txtData, GroupLayout.DEFAULT_SIZE, 207, Short.MAX_VALUE)
.addComponent(comboBox_Waluta, 0, 207, Short.MAX_VALUE)))
.addGroup(groupLayout.createSequentialGroup()
.addComponent(btnPobierzAktualne, GroupLayout.PREFERRED_SIZE, 207, GroupLayout.PREFERRED_SIZE)
.addGap(34)
.addComponent(btnZmieDat, GroupLayout.DEFAULT_SIZE, 207, Short.MAX_VALUE)))
.addContainerGap())
);
groupLayout.setVerticalGroup(
groupLayout.createParallelGroup(Alignment.TRAILING)
.addGroup(groupLayout.createSequentialGroup()
.addContainerGap()
.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 103, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.UNRELATED)
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING, false)
.addComponent(txtData, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(lblPodajDat, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(ComponentPlacement.RELATED)
.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
.addComponent(btnZmieDat)
.addComponent(btnPobierzAktualne, GroupLayout.PREFERRED_SIZE, 32, GroupLayout.PREFERRED_SIZE))
.addPreferredGap(ComponentPlacement.RELATED, 17, Short.MAX_VALUE)
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
.addComponent(comboBox_Waluta, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(lblWybierzWalut))
.addPreferredGap(ComponentPlacement.UNRELATED)
.addComponent(panel, GroupLayout.PREFERRED_SIZE, 142, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.UNRELATED)
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
.addComponent(txtKwota, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(lblPodajKwot))
.addPreferredGap(ComponentPlacement.UNRELATED)
.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
.addComponent(rdbtnWalutaNaZlote)
.addComponent(rdbtnZloteNaWalute))
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(btnPrzelicz)
.addPreferredGap(ComponentPlacement.UNRELATED)
.addComponent(lblWynik)
.addPreferredGap(ComponentPlacement.UNRELATED)
.addComponent(lblPrawdziwyWynik)
.addGap(33))
);
lblTabela = new JLabel("Tabela");
lblTabela.setFont(FONT_LABEL);
lbl_NumerTabeli = new JLabel("?");
lbl_NumerTabeli.setFont(new Font("Dialog", Font.BOLD, 24));
lblData = new JLabel("Data:");
lblData.setFont(FONT_LABEL);
lbl_DataTabeli = new JLabel("?");
lbl_DataTabeli.setFont(new Font("Dialog", Font.BOLD, 24));
GroupLayout gl_panel_1 = new GroupLayout(panel_1);
gl_panel_1.setHorizontalGroup(
gl_panel_1.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel_1.createSequentialGroup()
.addContainerGap()
.addGroup(gl_panel_1.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel_1.createSequentialGroup()
.addComponent(lblTabela, GroupLayout.PREFERRED_SIZE, 95, GroupLayout.PREFERRED_SIZE)
.addGap(18)
.addComponent(lbl_NumerTabeli, GroupLayout.PREFERRED_SIZE, 311, GroupLayout.PREFERRED_SIZE))
.addGroup(gl_panel_1.createSequentialGroup()
.addComponent(lblData, GroupLayout.PREFERRED_SIZE, 95, GroupLayout.PREFERRED_SIZE)
.addGap(18)
.addComponent(lbl_DataTabeli, GroupLayout.PREFERRED_SIZE, 311, GroupLayout.PREFERRED_SIZE)))
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
gl_panel_1.setVerticalGroup(
gl_panel_1.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel_1.createSequentialGroup()
.addContainerGap()
.addGroup(gl_panel_1.createParallelGroup(Alignment.LEADING)
.addComponent(lblTabela, GroupLayout.PREFERRED_SIZE, 29, GroupLayout.PREFERRED_SIZE)
.addComponent(lbl_NumerTabeli, GroupLayout.PREFERRED_SIZE, 29, GroupLayout.PREFERRED_SIZE))
.addGap(12)
.addGroup(gl_panel_1.createParallelGroup(Alignment.LEADING)
.addComponent(lblData, GroupLayout.PREFERRED_SIZE, 29, GroupLayout.PREFERRED_SIZE)
.addComponent(lbl_DataTabeli, GroupLayout.PREFERRED_SIZE, 29, GroupLayout.PREFERRED_SIZE))
.addContainerGap(21, Short.MAX_VALUE))
);
panel_1.setLayout(gl_panel_1);
JLabel lblKod = new JLabel("Kod:");
lblKod.setFont(FONT_LABEL);
JLabel lblNazwa = new JLabel("Nazwa:");
lblNazwa.setFont(FONT_LABEL);
JLabel lblKurs = new JLabel("Kurs:");
lblKurs.setFont(FONT_LABEL);
lbl_KodWaluty = new JLabel("kod");
lbl_KodWaluty.setFont(FONT_WARTOSC);
lbl_NazwaWaluty = new JLabel("nazwa");
lbl_NazwaWaluty.setFont(FONT_WARTOSC);
lbl_KursWaluty = new JLabel("1.0000");
lbl_KursWaluty.setFont(FONT_WARTOSC);
GroupLayout gl_panel = new GroupLayout(panel);
gl_panel.setHorizontalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addContainerGap()
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING, false)
.addComponent(lblKurs, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblNazwa, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lblKod, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 95, Short.MAX_VALUE))
.addPreferredGap(ComponentPlacement.RELATED, 18, GroupLayout.PREFERRED_SIZE)
.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addComponent(lbl_KodWaluty, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 171, Short.MAX_VALUE)
.addComponent(lbl_NazwaWaluty, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 171, Short.MAX_VALUE)
.addComponent(lbl_KursWaluty, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 171, Short.MAX_VALUE))
.addContainerGap())
);
gl_panel.setVerticalGroup(
gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup()
.addContainerGap()
.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
.addComponent(lblKod)
.addComponent(lbl_KodWaluty))
.addPreferredGap(ComponentPlacement.UNRELATED)
.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
.addComponent(lblNazwa)
.addComponent(lbl_NazwaWaluty))
.addPreferredGap(ComponentPlacement.UNRELATED)
.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
.addComponent(lblKurs)
.addComponent(lbl_KursWaluty))
.addContainerGap(61, Short.MAX_VALUE))
);
panel.setLayout(gl_panel);
frmPrzelicznikWalut.getContentPane().setLayout(groupLayout);
}
protected void przelicz() {
try {
BigDecimal kwota = new BigDecimal(txtKwota.getText());
String kod = "" + comboBox_Waluta.getSelectedItem();
Waluta waluta = tabela.findByCode(kod).get();
BigDecimal wynik = null;
if(rdbtnWalutaNaZlote.isSelected()) {
wynik = waluta.przeliczNaZlote(kwota);
}
if(rdbtnZloteNaWalute.isSelected()) {
wynik = waluta.przeliczNaWalute(kwota);
}
lblPrawdziwyWynik.setText("" + wynik);
lblPrawdziwyWynik.setForeground(Color.BLUE);
} catch (Exception e) {
lblPrawdziwyWynik.setText("błąd");
lblPrawdziwyWynik.setForeground(Color.RED);
}
}
protected void wyswietlDaneWaluty() {
String kod = "" + comboBox_Waluta.getSelectedItem();
Optional<Waluta> waluta = tabela.findByCode(kod);
if(waluta.isPresent()) {
lbl_KodWaluty.setText(waluta.get().getCode());
lbl_NazwaWaluty.setText(waluta.get().getCurrency());
lbl_KursWaluty.setText("" + waluta.get().getMid());
if(! txtKwota.getText().isEmpty()) {
przelicz();
}
return;
}
lblPrawdziwyWynik.setText("0.00");
lblPrawdziwyWynik.setForeground(Color.GRAY);
}
private void pobierzAktualneKursy() {
// Pobieranie aktualnych kursów w tle (to znaczy w innym wątku)
// Aby wykonać operację w tle, w Swingu najlepiej użyć klasy SwingWorker
SwingWorker<TabelaWalut, Void> worker = new SwingWorker<>() {
protected TabelaWalut doInBackground() {
try {
tabela = pobieranie.pobierzBiezaceKursy();
} catch(BladAplikacji e) {
tabela = new TabelaWalut("Brak danych", LocalDate.now());
e.printStackTrace();
}
return tabela;
}
protected void done() {
// tu piszemy "co ma zrobić okno, gdy operacja jest zakończona"
// to będzie wykonane przez wątek EDT
odswiezDaneTabeli();
wyswietlDaneWaluty();
}
};
worker.execute();
}
private void pobierzKursyDlaDaty() {
SwingWorker<TabelaWalut, Void> worker = new SwingWorker<>() {
protected TabelaWalut doInBackground() {
String data = txtData.getText();
try {
tabela = pobieranie.pobierzArchiwalneKursy(data);
SwingUtilities.invokeLater(() -> {
txtData.setForeground(Color.BLACK);
});
} catch(BladAplikacji e) {
tabela = new TabelaWalut("Brak danych", LocalDate.now());
e.printStackTrace();
}
return tabela;
}
protected void done() {
odswiezDaneTabeli();
wyswietlDaneWaluty();
}
};
worker.execute();
}
private void odswiezDaneTabeli() {
lbl_NumerTabeli.setText(tabela.getNo());
lbl_DataTabeli.setText("" + tabela.getEffectiveDate());
Object wybranaWaluta = comboBox_Waluta.getSelectedItem();
comboBox_Waluta.setModel(new DefaultComboBoxModel<>(tabela.codes()));
comboBox_Waluta.setSelectedItem(wybranaWaluta);
}
}
package waluty;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class TabelaWalut {
private final String no;
private final LocalDate effectiveDate;
private final List<Waluta> rates = new ArrayList<>();
public TabelaWalut(String no, LocalDate effectiveDate) {
this.no = no;
this.effectiveDate = effectiveDate;
}
public TabelaWalut(String no, String effectiveDate) {
this(no, LocalDate.parse(effectiveDate));
}
public void addRate(Waluta waluta) {
rates.add(waluta);
}
public String getNo() {
return no;
}
public LocalDate getEffectiveDate() {
return effectiveDate;
}
public List<Waluta> getRates() {
// 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.getCode().equals(code) ) {
return Optional.of(waluta);
}
}
return Optional.empty();
}
public String[] codes() {
return rates.stream()
.map(Waluta::getCode)
.toArray(String[]::new);
}
}
package waluty;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Waluta {
private final String code;
private final String currency;
private final BigDecimal mid;
public Waluta(String code, String currency, BigDecimal mid) {
this.code = code;
this.currency = currency;
this.mid = mid;
}
public String getCode() {
return code;
}
public String getCurrency() {
return currency;
}
public BigDecimal getMid() {
return mid;
}
@Override
public String toString() {
return code + " (" + currency + "): " + mid;
}
public BigDecimal przeliczNaZlote(BigDecimal kwota) {
return kwota.multiply(mid).setScale(2, RoundingMode.HALF_EVEN);
}
public BigDecimal przeliczNaWalute(BigDecimal kwota) {
return kwota.divide(mid, 2, RoundingMode.HALF_EVEN);
}
}
https://api.nbp.pl/
https://api.nbp.pl/api/exchangerates/tables/A/
https://api.nbp.pl/api/exchangerates/tables/B/
https://api.nbp.pl/api/exchangerates/tables/C/
https://api.nbp.pl/api/exchangerates/tables/A/2020-02-05
https://api.nbp.pl/api/exchangerates/tables/A/?format=xml
https://api.nbp.pl/api/exchangerates/tables/A/?format=json
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