Lab01 Napisz aplikację, która pozwoli na archiwizowanie wskazanych plików/katalogów. Aplikacja ta powinna równiez umożliwiać generowanie funkcji skrótu MD5 dla stworzonych archiwów oraz weryfikowanie, czy dana funkcja skrótu zgadza się z funkcją skrótu wyliczoną dla danego archiwum. Proszę zastanowić się nad interfejsem użytkownika tej aplikacji (w jaki sposób definiować zadanie archiwizacji, w tym miejsca do zapisu archiwów oraz funkcji skrótu oraz miejsca do ich odczytu). Można przyjąć różne strategie co do sposobu zapamiętywania funkcji skrótu (np. w tym samym katalogu, w którym zapisano archiwum, o tej samej nazwie co archiwum, ale z innym rozszerzeniem). Aplikacja powinna być napisana z wykorzystaniem modułów (wprowadzonych w Javie od jdk 9). Powstać ma przynajmniej jeden moduł biblioteki oraz moduł samej aplikacji (korzystający z modułu biblioteki). Powstałe moduły należy wyeksportować do plików jar. Używając jlink należy przygotować minimalne środowisko uruchomieniowe, do którego podpięte zostaną wymienione wyżej moduły. Aplikację powinno dać się uruchomić z linii komend, korzystając tylko z wygenerowanego środowiska uruchomieniowego. Sama aplikacja powinna oferować interfejs użytkownika (najlepiej graficzny, minimum - tekstowy). Sprawę tworzenia archiwów (zipowania) nieźle opisano w tutorialu: https://www.baeldung.com/java-compress-and-uncompress Można z niego skorzystać. Lab02 Napisz aplikację, która umożliwi przeglądanie danych pomiarowych przechowywanych na dysku w plikach csv (w wersji minimum). Zakładamy, że pliki danych będą składowane w folderach o nazwach reprezentujących daty kampanii pomiarowych (np. nazwą folderu może być 07.03.2023), zaś nazwy samych plików będą odpowiadały identyfikatorowi stanowiska pomiarowego oraz godzinie rozpoczęcia pomiarów (np. nazwą pliku może być 0001_10:00). Zawartość plików powinna odpowiadać następującemu schematowi: # godzina pomiaru; ciśnienie [hPa]; temperatura [stopnie C]; wilgotność [%] 10:00; 960,34; -1,2; 60; 10:02; 960,34; -1,2; 60; .... Pliki danych można stworzyć do testów posługując się generatorami losowymi czy innymi narzędziami. Interfejs graficzny aplikacji powinien składać się z dwóch paneli - jednego, przeznaczonego do nawigacji po folderach i plikach, oraz drugiego, służącego do wyświetlania podglądu zawartości aktualnie wybranego pliku z danymi (wyświetlanych może być kilka pierwszych linijek) oraz wyników przetworzenia danych (wartości średnich dla kolejnych kolumn, poza kolumną z godziną pomiaru). Aplikację należy zaprojektować z wykorzystaniem słabych referencji (ang. weak references). Zakładamy, że podczas przeglądania folderów z plikami danych pomiarowych zawartość aktualnie wybranego pliku będzie ładowana do odpowiedniej struktury oraz zostanie przetworzona (celem wyliczenia odpowiednich wartości). Słabe referencje powinny pozwolić na ominięcie konieczności wielokrotnego ładowania i przetwarzania tej samej zawartości - co może nastąpić podczas poruszanie się wprzód i wstecz po liście plików w folderach. Aplikacja powinna wskazywać, czy zawartość pliku została załadowana ponownie, czy też została pobrana z pamięci. Wskazanie to może być zrealizowane za pomocą jakiegoś znacznika prezentowanego na interfejsie. W celu oceny poprawności działania aplikację należy uruchamiać przekazując wirtualnej maszynie parametry ograniczające przydzielaną jej pamięć. Na przykład -Xms512m (co oznacza minimalnie 512 MB pamięci), -Xmx1024m (co oznacza maksymalnie 1GB). Należy też przetestować możliwość regulowania zachowania się algorytmu odśmiecania, do czego przydają się opcje -XX:+ShrinkHeapInSteps, -XX:-ShrinkHeapInSteps. Proszę przestudiować, jakie inne atrybuty można przekazać do wirtualnej maszyny, w tym selekcji algorytmu -XX:+UseSerialGC, -XX:+UseParNewGC (deprecated), -XX:+UseParallelGC, -XX:+UseG1GC. Architektura aplikacji powinna umożliwiać dołączanie różnych algorytów przetwarzania danych, jak również algorytmów renderujących fragment zawartości przeglądanego pliku (zakładamy, że aplikację będzie można rozbudować w celu przeglądania danych zapisanych w plikach o innym schemacie zawartości czy też innym formacie danych). Proszę dodać do źródeł plik readme.md z wnioskami co do stosowalności opcji wirtualnej maszyny. Proszę sięgnąć do materiałów http://tomasz.kubik.staff.iiar.pwr.wroc.pl/dydaktyka/Java/UnderstandingWeakReferences.pdf Lab03 Napisz aplikację, która pozwoli skonsumować dane bibliograficzne pozyskiwane z serwisu oferującego publiczne restowe API. Serwisem takim może być: https://openlibrary.org/developers/api lub jakikolwiek inny serwis, z którym można będzie się skomunikować (spełniając wymagania określone w treści zadania). Nawiasem mówiąc ciekawą listę serwisów udostępniających API można znaleźć pod adresem: https://rapidapi.com/collection/list-of-free-apis (wymagają klucza API), czy też https://mixedanalytics.com/blog/list-actually-free-open-no-auth-needed-apis/ (te klucza API nie wymagają). Bazując na wskazanym api należy zbudować aplikację z graficznym interfejsem użytkownika, pozwalającą na przeprowadzanie testów dla bibliofilów, z pytaniami dotyczącymi książek (np. tytuły, tematyka, wydania, autorzy), autorów (np. dorobek wydawniczy, współautorstwo) itp. Renderowanie zapytań i odpowiedzi powinno być tak zaimplementowane, by dało się zmianić ustawienia językowe (lokalizacji) w oparciu o tzw. bundle (definiowane w plikach i klasach - obie te opcje należy przetestować). Wspierane mają być języki: polski i angielski. Proszę zapoznać się z api i zaproponować kilka schematów zapytań i pól odpowiedzi. Niech zapytania będą parametryzowane wartościami pochodzącymi z list wyboru wypełnionych treścią pozyskaną z serwisu, a odpowiedzi niech będą uzupełniane wolnym tekstem lub wartościami z list wyboru (jeśli "charakter" pytania jest, odpowiednio, otwarty lub zamknięty). Odpowiedzi podanawane przez użytkownika powinny być weryfikowane przez aplikację (aplikacja, po wysłaniu zapytania przez api powinna sprawdzić, czy wynik tego zapytania jest zgodny z odpowiedzią udzieloną przez użytkownika). Przykłady szablonów zapytania i odpowiedzi: Przykład 1: Pole zapytania: "Kto jest autorem książki ... ?" (w miejsce kropek aplikacja powinna wstawić jakiś tytuł pobrany z serwisu) Pole odpowiedzi: "..." (miejsce na wpisanie autora). Pole weryfikacji (dla poprawnej odpowiedzi): "Tak, masz rację. Autorem książki .... jest ..." (to ma wypełnić sama aplikacja, przy czym można się zastanowić nad tym, jak ma przebiegać weryfikacja, gdy np. autorów jest więcej niż jeden). Przykład 2: Na przykład dla szablonu zapytania zapytania: Pole zapytania: "Ilu współatorów ma książka ... ?" (w miejsce kropek aplikacja powinna wstawić jakiś tytuł pobrany z serwisu) Pole odpowiedzi: "..." (miejsce na wpisanie liczby). Pole weryfikacji (dla poprawnej odpowiedzi): "Tak, masz rację. Książka ... została napisana przez ... autorów" (to ma wypełnić sama aplikacja, przy czym trzeba obsłużyć odmianę przez liczby). Przykład 3: Pole zapytania: "Które z wymienionych tytułów: a) ...., b) ...., c) ....., d) ..... to książki dotyczące tematyki: ....?" (w miejsce kropek przy wyliczeniu aplikacja powinna wstawić losowe tytuły książek pobrane z serwisu, zaś tematyka powinna być atrybutem pasującym przynajmniej do jednego tytułu - co można sprawdzić w serwisie). Pole odpowiedzi: "..." (miejsce na wpisanie literki/literek odpowiadających wybranym tytułom). Pole weryfikacji (dla poprawnej odpowiedzi): "Tak, masz rację. Książka (bądź książki) ... dotyczy (dotyczą) tematyki ....." (to ma wypełnić sama aplikacja, przy czym trzeba obsłużyć odmianę przez liczby). Proszę pamiętać o obsłudze przynajmniej dwóch języków na interfejsie. Do tego proszę zastosować wariantowe pobieranie tekstów z bundli. Do tego przyda się klasa ChoiceFormat. Przypominam, że podczas realizacji zadania można wykorzystać inne api niż sugerowane, jeśli tylko pozwoli ono zrealizować przedstawioną wyżej koncepcję (parametryzowane szablony zapytań, do wypełnienia pola odpowiedzi, linijka weryfikacji z odmianą przez liczby/osoby - wszystko przynajmniej z obsługą dwóch języków: polski i angielski). Lab04 Napisz aplikację, która umożliwi zlecanie wykonywania zadań instancjom klas ładowanym własnym ładowaczem klas. Do realizacji tego ćwiczenia należy użyć Java Reflection API z jdk 17. Tworzona aplikacja powinna udostępniać graficzny interfejs, na którym będzie można: 1. zdefiniować zadanie (zakładamy, że będzie można definiować "dowolne" zadania reprezentowane przez ciąg znaków), 2. załadować klasę wykonującą zadanie (zakładamy, że będzie można załadować więcej niż jedną taką klasę), 3. zlecić wykonanie wskazanego zadania wskazanej załadowanej klasie, monitorować przebieg wykonywania zadania, wyświetlić wynik zadania. 4. wyładować wybraną klasę z wcześniej załadowanych Realizacja zadania powinna opierać się na wykorzystaniu API (klas i interfejsów) zdefiniowanych w archiwum Refleksja02.zip. Należy dostarczyć przynajmniej 3 różne klasy implementujące interfejs Processor. Każda taka klasa po załadowaniu powinna oznajmić, poprzez wynik metody getInfo(), jakiego typu zadanie obsługuje. Na przykład pozyskana informacja w postaci "sumowanie" oznaczałaby, że zadanie można zdefiniować ciągiem znaków "1 + 2", gdzie oczekiwanym wynikiem byłoby "3". Informacja "zamiana małych liter na duże" oznaczałaby, że dla zadania "abc" oczekiwanym wynikiem ma być "ABC". Klasy ładowane powinny być skompilowane w innym projekcie niż sama użytkowa aplikacja (podczas budowania aplikacja nie powinna mieć dostępu do tych klas). Można założyć, że kod bajtowy tych klas będzie umieszczany w katalogu, do którego aplikacja będzie miała dostęp. Ścieżka do tego katalogu powinna być parametrem ustawianym w aplikacji w trakcie jej działania. Wartością domyślną dla ścieżki niech będzie katalog, w którym uruchomiono aplikację. Aplikacja powinna odczytać zawartość tego katalogu i załadować własnym ładowaczem odnalezione klasy. Zakładamy, że podczas działania aplikacji będzie można "dorzucić" nowe klasy do tego katalogu (należy więc pomyśleć o pewnego rodzaju "odświeżaniu"). Wybieranie klas (a tym samym algorytmów przetwarzania) powinno odbywać się poprzez listę wyświetlającą nazwy załadowanych klas. Nazwom tym niech towarzyszą opisy pozyskane metodą getInfo() z utworzonych instancji tych klas. Zlecanie zadań instancjom klas powinno odbywać się poprzez metodę submitTask(String task, StatusListner sl). W metodzie tej należy podać słuchacza typu StatusListener, który będzie otrzymywał informacje o zmianie statusu przetwarzania. Do reprezentacji statusu przetwarzania służy klasa Status (klasę tę zadeklarowano tak, aby po utworzeniu statusu jego atrybuty były tylko do odczytu). Proszę przetwarzanie zaimplementować w wątku z opóźnieniami, by dało się monitorować bieżący status przetwarzania. Do monitorowania statusów przetwarzania i wyświetlania wyników można użyć osobnej listy (monitora zadań) wyświetlanej na interfejsie aplikacji. Proszę napisać własny (!) ładowacz klas. Ładowacz ten może być klasą, do której przekazana zostanie ścieżka położenia kodów bajtowych ładowanych klas z algorytmami przetwarzania. Własny ładowacz nie może rozszerzać klasy URLClassLoader. Ponieważ aplikacja ma być rozwijana w jdk17 należy zastanowić się, jak w takim przypadku obsłużyć warstwy modułowe (podpinając im ładowacze klas). Klasy załadowane powinno dać się wyładować. Proszę pamiętać, że klasa zostanie wyładowana, gdy znikną wszystkie referencje od jej instancji oraz gdy zniknie referencja do ładowacza, który tę klasę załadował (i zadziała odśmiecanie). Można monitorować liczbę załadowanych i wyładowanych klas za pomocą jconsole lub jmc. Proszę zajrzeć do materiałów wymienionych przy wykładzie o refleksji i ładowaczach klas. Lab05 Zaimplementuj aplikację z graficznym interfejsem pozwalającą przeprowadzić analizę statystyczną wyników klasyfikacji zgromadzonych w tzw. tabelach niezgodności (ang. confusion matrix). Obliczać należy współczynnik kappa oraz przynajmniej trzy inne miary (np. miary opisane w artykule: https://arxiv.org/pdf/2008.05756.pdf). Aplikacja powinna pozwalać na: - wyświetlanie/edytowanie danych tabelarycznych; - wybranie algorytmu, jakim będą one przetwarzane; - wyświetlenie wyników przetwarzania (obliczonej miary). W trakcie implementacji należy wykorzystać interfejs dostarczyciela serwisu (ang. Service Provider Interface, SPI). Dokładniej, stosując podejście SPI należy zapewnić aplikacji możliwość załadowania klas implementujących zadany interfejs już po zbudowaniu samej aplikacji. Klasy te (z zaimplementowanymi algorytmami wyliczającymi miary służące do oceny wyników klasyfikacji) mają być dostarczane w plikach jar umieszczanych w ścieżce. Należy stworzyć dwie wersje projektu: standardową oraz modularną. Aby zapoznać się z problemem proszę sięgnąć do przykładowych projektów w archiwum udostępnionym pod adresem: http://tomasz.kubik.staff.iiar.pwr.wroc.pl/dydaktyka/Java/WorkspaceServiceProviderInterface.zip W implementacji należy wykorzystać klasy z pakietu ex.api dostarczanego przez bibliotekę: http://tomasz.kubik.staff.iiar.pwr.wroc.pl/dydaktyka/Java/analysisserviceapi-1.0-SNAPSHOT.jar (ten modułowy jar zawiera kod bajtowy oraz kod źródłowy klas: AnalysisException, AnalysisService, DataSet). Trochę informacji o SPI można znaleźć pod adresem: https://www.baeldung.com/java-spi Porównanie SPI ze SpringBoot DI zamieszczono pod adresem: https://itnext.io/serviceloader-the-built-in-di-framework-youve-probably-never-heard-of-1fa68a911f9b Lab06 Napisz program, który pozwoli zasymulować działanie narzędzia do obsługi klientów firmy będącej dostawcą Internetu (zakładamy, że program będzie działał w kontekście dostawcy Internetu). Zadanie należy zrealizować wykorzystując relacyjną bazę danych. Zalecane jest użycie h2 (z zapisem do pliku) bądź sqlite. Podczas realizacji zadania należy skorzystać z mapowania ORM (technologia JPA, do czego można użyć framework Hibernate). Wtedy jednak należy zastosować wzorzec projektowy z użyciem serwisów. Generalnie projekt może być zrealizowany z użyciem frameworka Spring Boot (warstwa serwisów i repozytoriów). Zakładamy, że w bazie danych będą przechowywane następujące informacje (jest to model mocno uproszczony w porównaniu do modeli spotykanych w rzeczywistości): Kient - imię, nazwisko, numer klienta Instalacja - adres, numer routera, typ usługi Naliczone należności - termin płatności, kwota do zapłaty Dokonane wpłaty - termin wpłaty, kwota wpłaty Cennik - typ usługi, cena Dla jednego klienta może być założonych wiele instalacji. Należności i wpłaty dotyczą danej instalacji. Należności naliczane są w trybie miesięcznym. Cennik dotyczy wszystkich typów usługi (aktywnych, wygasłych, nowych). Program powinien: - umożliwiać ręczne zarządzanie danymi klientów, danymi instalacji oraz cennikiem - automatycznie naliczać należności i wysyłać monity o kolejnych płatnościach (wystarczy, że będzie pisał do pliku z logami monitów, upływ czasu należy zasymulować). - automatycznie eskalować monity w przypadku braku terminowej wpłaty (wystarczy, że będzie pisał do pliku z logami ekalowanych monitów, upływ czasu należy zasymulować) - umożliwiać ręczne rejestrowanie wpłat oraz nanoszenie korekt - umożliwiać przeglądanie należności i wpłat Program może działać w trybie konsolowym, choć dużo lepiej wyglądałoby stworzeni interfejsu graficznego. Do logowania monitów proszę użyć jakąś standardową bibliotekę (np. log4j). Lab07 Zamień aplikację napisaną podczas poprzedniego labotatorium na usługę sieciową. Niech ta usługa będzie oferowała restowy interfejs pozwalający na wykonanie wszystkich operacji związanych z obsługą klientów firmy będącej dostawcą Internetu, a jej implementacja niech będzie wykonana z pomocą frameworka Spring Boot. Implementacja może odbywać się według podejścia top-down (czyli najpierw definicja interfejsu wykonana w Swagger Editor, a potem wygenerowanie kodu źródłowego interfejsów i ich implementacja), albo według podejścia bottom-up (czyli najpierw redagowanie kodu źródłowego interfejsów i ich implementacja, a potem wygenerowanie swaggerowego opisu). Efektem ma być tzw. backend, którego działanie będzie można: * przetestować za pomocą swaggerowego interfejsu (automatycznie wygenerowanej strony internetowej, dającej możliwość sparametryzowania zapytań protokołu HTTP, ich wysłania na endpoint oraz wyświetlenia wyniku); * przetestować za pomocą zewnętrznych narzędzi jak: Postman czy SoapUI. Reszta wymagań zgodnie z ustaleniami poczynionymi na laboratorium. Lab08 Napisz program, w którym wykorzystane zostanie JNI. Zadanie do wykonania polegać ma na zadeklarowaniu klasy Java z dwiema metodami służącymi do obliczania dyskretnej dwuwymiarowej funkcji splotu (ang. 2D discrete convolution function): natywną oraz normalną, a następnie przetestowaniu ich działania. Metoda do obliczania splotu powinna przyjmować na wejście dwie tablice dwuwymiarowe (jądro splotu oraz macierz przetwarzaną) oraz produkować na wyjściu wynik (macierz wynikową). O tym, czym jest funkcji splotu, poczytać sobie można w wielu tutorialach, np. w dokumencie https://staff.uz.zgora.pl/agramack/files/conv/Splot.pdf Podczas testowania należy wygenerować odpowiednio duży problem obliczeniowy, a potem spróbować go rozwiązać korzystająć z obu zaimplementowanych metod. Testowanie powinno dać odpowiedź na pytanie, która z implementacji jest wydajniejsza. Stąd uruchamianiu metod powinno towarzyszyć mierzenie czasu ich wykonania (czyli coś na kształt testów wydajnościowych). Sposób wykonania takich testów jest dowolny, jednak warto spróbować wykorzystać do tego np. framework Mockito. Jako wynik zadania, oprócz kodów źródłowych Java oraz kodu zaimplementowanej natywnej biblioteki, należy dostarczyć również raport z omówieniem wyników testowania. Proszę zwrócić uwagę na to, czy podczas testów nie uwidoczniło się działanie JIT. Lab09 Podczas laboratoriów należy przećwiczyć różne sposoby przetwarzania dokumentów XML. Aby zadanie nie było zbyt skomplikowane, a jednocześnie umożliwiało zapoznanie się z różnymi technologiami, zdefiniowano je w następujący sposób: Napisz program pozwalający: 1. wczytać dane XML korzystając z JAXB i wyrenderować je na ekranie (tutaj należy zdefiniować klasę mapującą się do struktury dokumentu XML oraz skorzystać z serializatora/deserializatora). 2. wczytać dane XML korzystając z JAXP i wyrenderować je na ekranie (tutaj należy uruchomić parsery SaX i DOM). 3. przetworzyć dane z dokumentu XML za pomocą wybranego arkusza transformacji XSLT i wyświetlić wynik tego przetwarzania. Przetwarzanie może polegać na wygenerowaniu i wyrenderowaniu htmla powstałego na skutek zaaplikowania wybranego arkusza XSLT do dokumentu XML (arkusz może "wycinać" niektóre elementy, "wyliczać" jakieś wartości, ostylowywać tekst itp.). Program powinien umożliwić wybór używanego arkusza spośród kilku arkuszy składowanych w zadanym miejscu. Chodzi tu, między innymi, o to, by dało się zmienić "działanie programu" już po jego kompilacji (poprzez podmianę/wskazanie używanego arkusza). Dane XML do przetwarzania mają pochodzić z publicznie dostępnych repozytoriów (z licencjami pozwalającymi na ich użytkowanie przynajmniej do celów edukacyjnych). Na przykład mogą do być dane opublikowane pod linkami: https://bip.poznan.pl/api-xml/bip/dane-o-srodowisku-i-ochronie/A/, https://catalog.data.gov/dataset/popular-baby-names, https://www.floatrates.com/feeds.html, Dane mogą dotyczyć np. wyników piłkarskich rozgrywek ligowych (często dane te udostępniane są na komercyjnych zasadach, ale istnieją też darmowe przykłady do pobrania, jak: http://xmldocs.sports.gracenote.com/XML-Downloads-and-Samples_1048597.html) Istnieje coś takiego jak "xml feeds"(strumienie danych XML), w szczególności "atom feeds" - ale to jest temat do osobnego omówienia (patrz https://www.ibm.com/docs/en/cics-ts/5.5?topic=support-overview-atom-feeds).