Курсова робота (2 курс) — Java-версія
Цей проєкт — система автоматизації бібліотечного фонду, розроблена на мові програмування Java 17 з використанням бази даних PostgreSQL. Система забезпечує ефективне управління бібліотечними ресурсами: книгами, читачами, бібліотеками, бібліотекарями та статистикою відвідувань.
Інтерфейс розроблено для двох типів користувачів: бібліотекарів, які здійснюють основну діяльність з обробки даних, та адміністраторів, які мають повний доступ до функцій керування системою.
Консольний UI побудований на Lanterna — Java-аналозі бібліотеки ftxui, яку використовує оригінальна C++ версія цього проєкту: кольорові кнопки, рамки, прокручувані списки, навігація стрілками/Tab/Enter і повноцінний клік мишею.
| Назва | Призначення | |
|---|---|---|
| ☕ | Java 17 | Основна мова програмування |
| 🐘 | PostgreSQL | Система управління базами даних |
| 📦 | Maven 3.8+ | Збірка проєкту, залежності, тести, пакування |
| 💻 | IntelliJ IDEA | Середовище розробки |
| 🔄 | Git | Система керування версіями |
| 🔗 | PostgreSQL JDBC | Драйвер для роботи з PostgreSQL — jdbc.postgresql.org |
| ✨ | Lanterna | Бібліотека для консольного UI — github.com/mabe02/lanterna |
| 🧪 | JUnit 5 + Mockito | Модульне тестування |
| 📦 | jpackage | Збірка нативного .exe (входить до JDK, з версії 14) |
-
Завантаж PostgreSQL з офіційного сайту: 👉 postgresql.org/download
-
Під час встановлення запам'ятай пароль користувача
postgres— він знадобиться далі. -
Переконайся, що
bin-папка PostgreSQL (наприклад,C:\Program Files\PostgreSQL\16\bin) додана до системної змінноїPath, щоб командиpsql,createdb,pg_restoreбули доступні з будь-якої консолі.
Є два способи підготувати базу: Варіант А створює порожню схему з нуля, Варіант Б відновлює з готового дампу.
createdb -U postgres library
psql -U postgres -d library -f schema.sqlМінімальний набір таблиць (schema.sql), на якому побудовані всі запити проєкту:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
role TEXT NOT NULL,
login TEXT NOT NULL UNIQUE,
password TEXT NOT NULL
);
CREATE TABLE libraries (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
location TEXT
);
CREATE TABLE librarians (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE work_schedule (
id SERIAL PRIMARY KEY,
worker_id INTEGER REFERENCES librarians(id),
library_id INTEGER REFERENCES libraries(id),
start_day TEXT,
end_day TEXT,
start_time TEXT,
end_time TEXT
);
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL
);
CREATE TABLE book_details (
book_id INTEGER PRIMARY KEY REFERENCES books(id),
genre TEXT,
publisher TEXT,
year INTEGER,
isbn TEXT
);
CREATE TABLE book_authors (
book_id INTEGER REFERENCES books(id),
author_id INTEGER REFERENCES authors(id),
PRIMARY KEY (book_id, author_id)
);
CREATE TABLE categories (
id SERIAL PRIMARY KEY,
category_type TEXT NOT NULL
);
CREATE TABLE readers (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
address TEXT,
phone TEXT
);
CREATE TABLE category_details (
reader_id INTEGER PRIMARY KEY REFERENCES readers(id),
category_id INTEGER REFERENCES categories(id),
institution_name TEXT,
major TEXT,
school_number TEXT,
kindergarten_name TEXT,
research_field TEXT
);
CREATE TABLE visits (
id SERIAL PRIMARY KEY,
reader_id INTEGER REFERENCES readers(id),
book_id INTEGER REFERENCES books(id),
library_id INTEGER REFERENCES libraries(id),
visit_time TIMESTAMP NOT NULL DEFAULT now()
);
-- Обліковий запис адміністратора для першого входу:
INSERT INTO users (role, login, password) VALUES ('admin', 'admin', 'admin');
-- Хоча б одна бібліотека, щоб можна було зареєструвати бібліотекаря:
INSERT INTO libraries (name, location) VALUES ('Central Library', 'Main St 1');# 1. Створити базу даних
createdb -U postgres library
# 2. Перейти до папки з дампом (вкажи свій шлях)
cd "D:\Download\libcode-java\database"
# 3a. Відновлення з текстового SQL-дампу
psql -U postgres -d "library" -f "library.sql"
# 3b. Відновлення з бінарного дампу (pg_dump --format=custom)
pg_restore -U postgres -d "library" -c "library.dump"При виконанні команд система може запитати пароль користувача
postgres. Після відновлення переконайся, що вusersє хоча б один рядок зrole = 'admin', а вlibraries— хоча б один запис.
На відміну від C++ версії, пароль не зашивається в код — усе підключення до БД читається зі змінних середовища, зі зручними значеннями за замовчуванням:
| Змінна | Значення за замовчуванням | Опис |
|---|---|---|
LIBRARY_DB_URL |
jdbc:postgresql://localhost:5432/library |
JDBC-рядок підключення |
LIBRARY_DB_USER |
postgres |
Користувач БД |
LIBRARY_DB_PASSWORD |
admin1 |
Пароль користувача БД |
# PowerShell
$env:LIBRARY_DB_URL = "jdbc:postgresql://localhost:5432/library"
$env:LIBRARY_DB_USER = "postgres"
$env:LIBRARY_DB_PASSWORD = "твій_пароль"# bash / zsh
export LIBRARY_DB_URL="jdbc:postgresql://localhost:5432/library"
export LIBRARY_DB_USER="postgres"
export LIBRARY_DB_PASSWORD="твій_пароль"Якщо змінні не задані — застосунок підключається за значеннями за замовчуванням із таблиці вище.
Проєкт збирається Maven — жодних додаткових пакетних менеджерів (на кшталт vcpkg) не потрібно, усі залежності (Lanterna, PostgreSQL JDBC, JUnit, Mockito) підтягуються автоматично з Maven Central.
git clone https://github.com/VSCRM/Library.git
cd Librarymvn clean package
java -jar target/library-console.jarmvn package компілює код, прогонить весь набір тестів і (через maven-shade-plugin) створює єдиний самодостатній library-console.jar з уже вбудованим драйвером PostgreSQL — окремо налаштовувати classpath не потрібно.
mvn testНабір тестів (JUnit 5 + Mockito) перевіряє кожен клас через його публічний контракт — реальна база даних для запуску тестів не потрібна: усі виклики java.sql.* підмінені моками.
Окремий Maven-профіль exe одразу після пакування запускає jpackage, тож один командний рядок дає одразу і .jar, і .exe:
mvn clean package -PexeРезультат — target\LibCodeLibraryConsole\LibCodeLibraryConsole.exe, який можна запускати напряму: цільова машина не потребує встановленої Java. Профіль вимагає повний JDK (не лише JRE) з jpackage на PATH — саме тому це окремий opt-in профіль, а не частина стандартної збірки: звичайний mvn package так само коректно працює на будь-якій платформі/CI.
ℹ️
.exeзбирається без консольного вікна: увесь реальний інтерфейс застосунку малюється у власному Swing-вікні Lanterna (див.LanternaScreens), тож окрема консоль Windows не потрібна.
Ручний виклик jpackage (якщо потрібно кастомізувати прапорці):
mvn clean package
jpackage --input target --main-jar library-console.jar --main-class com.libcode.library.Main --name LibCodeLibraryConsole --type app-image --dest targetЗамість --type app-image можна вказати --type msi або --type exe (потребує WiX Toolset) для отримання одного файла-інсталятора замість папки.
Це очікувано, а не пропущений крок: Java компілюється в байткод, а не в машинний код конкретної ОС/CPU, тож .jar виконується без змін на Windows/macOS/Linux, поки на машині є JVM. Саме тому стандартний спосіб поширення Java-застосунку — це .jar + java -jar .... Якщо потрібен саме нативний подвійним-кліком запускний файл для користувачів без Java — для цього і є jpackage (профіль exe вище).
Проєкт побудований на пошаровій архітектурі (UI → координація → бізнес-логіка → доступ до БД) і використовує наступні патерни проєктування:
| Патерн | Клас(и) | Призначення |
|---|---|---|
| Singleton | logging.Logger |
Єдина точка запису подій з таймстампом у log.txt |
| Proxy | auth.AuthorizationProxy → auth.Authorization |
Обмеження часу входу (07:00–16:00) перед делегуванням реальній перевірці |
| Abstract Factory | interfaces.IDBFactory / db.PostgresFactory |
Створення пари пов'язаних об'єктів доступу до БД (з'єднання + вивід) |
| Facade | ApplicationCoordinator.java |
Координація взаємодії між компонентами |
| Factory Method | interfaces.IMenuCreator / menu.MenuCreator |
Динамічне створення AdminMenu або LibrarianMenu залежно від ролі |
| Decorator | ui.ConsoleUtilsDecorator |
Стилізація консольного виведення без зміни базової реалізації |
| Adapter | db.ResultAdapter |
Конвертація java.sql.ResultSet у формат IDBOutput |
SOLID застосовано послідовно у всьому проєкті: кожен клас відповідає за одну задачу (SRP), нові ролі/меню/джерела даних додаються реалізацією інтерфейсу без зміни наявного коду (OCP), вузькі рольові інтерфейси (IBaseOperations, IAddOperations) замість одного великого (ISP), а всі залежності передаються через конструктор (DIP) — саме це і робить можливим тестування без реальної БД.
Повний перелік усіх файлів проєкту (кожна папка — за алфавітом: спершу підпапки, потім файли):
libcode-java/
├── data/ # DB — дампи бази даних, для відновлення
│ ├── library.dump
│ └── library.sql
├── src/
│ ├── main/java/com/libcode/library/
│ │ ├── app/ # Facade — координація застосунку
│ │ │ └── ApplicationCoordinator.java
│ │ ├── auth/ # Авторизація + Proxy обмеження часу
│ │ │ ├── Authorization.java
│ │ │ └── AuthorizationProxy.java
│ │ ├── db/ # Abstract Factory + Adapter для PostgreSQL
│ │ │ ├── PostgresConnection.java
│ │ │ ├── PostgresFactory.java
│ │ │ ├── PostgresOutput.java
│ │ │ └── ResultAdapter.java
│ │ ├── features/ # Бізнес-логіка бібліотекаря/адміністратора
│ │ │ ├── ExtendFeatures.java
│ │ │ └── MainFeatures.java
│ │ ├── interfaces/ # Усі контракти (I*.java)
│ │ │ ├── IAddOperations.java
│ │ │ ├── IApplicationCoordinator.java
│ │ │ ├── IAuthorization.java
│ │ │ ├── IBaseOperations.java
│ │ │ ├── IConsoleUtils.java
│ │ │ ├── IDBConnect.java
│ │ │ ├── IDBFactory.java
│ │ │ ├── IDBOutput.java
│ │ │ ├── IMenu.java
│ │ │ ├── IMenuCreator.java
│ │ │ ├── IUserContext.java
│ │ │ └── UserContextFactory.java
│ │ ├── logging/ # Singleton — журналювання подій
│ │ │ └── Logger.java
│ │ ├── menu/ # Factory Method — меню за роллю
│ │ │ ├── AdminMenu.java
│ │ │ ├── LibrarianMenu.java
│ │ │ └── MenuCreator.java
│ │ ├── model/ # Дані, що передаються між шарами
│ │ │ ├── LoginCredentials.java
│ │ │ └── UserContext.java
│ │ ├── ui/ # Lanterna-інтерфейс + Decorator стилізації
│ │ │ ├── AnsiColors.java
│ │ │ ├── ConsoleTheme.java
│ │ │ ├── ConsoleUtils.java
│ │ │ ├── ConsoleUtilsDecorator.java
│ │ │ ├── EndOfInputException.java
│ │ │ ├── LanternaScreens.java # спільне вікно + підтримка кліку/наведення мишею
│ │ │ ├── MarqueeListItemRenderer.java
│ │ │ └── MarqueeTicker.java
│ │ ├── util/ # Спільні допоміжні класи
│ │ │ ├── ConsoleInputReader.java
│ │ │ ├── DropdownSelector.java
│ │ │ ├── SqlTransactions.java
│ │ │ └── SystemTextEditor.java
│ │ └── Main.java # точка входу (composition root)
│ └── test/java/com/libcode/library/
│ ├── app/
│ │ └── ApplicationCoordinatorTest.java
│ ├── auth/
│ │ ├── AuthorizationProxyTest.java
│ │ └── AuthorizationTest.java
│ ├── db/
│ │ ├── PostgresConnectionTest.java
│ │ ├── PostgresFactoryTest.java
│ │ ├── PostgresOutputTest.java
│ │ └── ResultAdapterTest.java
│ ├── features/
│ │ ├── ExtendFeaturesTest.java
│ │ ├── LanternaKeystrokes.java # спільні хелпери для симуляції клавіш у тестах
│ │ └── MainFeaturesTest.java
│ ├── logging/
│ │ └── LoggerTest.java
│ ├── menu/
│ │ ├── AdminMenuTest.java
│ │ ├── LibrarianMenuTest.java
│ │ └── MenuCreatorTest.java
│ ├── model/
│ │ └── UserContextTest.java
│ ├── ui/
│ │ ├── ConsoleUtilsDecoratorTest.java
│ │ ├── ConsoleUtilsTest.java
│ │ ├── LanternaScreensTest.java # математика піксель→комірка (клік/наведення мишею)
│ │ └── MouseHoverSelectionTest.java # виділення рухається за наведенням миші, як стрілками
│ └── util/
│ └── ConsoleInputReaderTest.java
├── .gitignore
├── LICENSE
├── pom.xml
└── README.md
(target/, .idea/ та інші згенеровані/IDE-папки навмисно виключені — див. .gitignore.)
- Information about books — перелік усіх книг (назва, автор, жанр, видавництво, рік, ISBN) через
JOINтаблицьbook_details,book_authors,authors - Information about readers — перелік читачів та їхньої категорії (
JOINзcategory_details,categories) - Information about visits — історія відвідувань (
JOINvisits,readers,libraries,books) - Most popular books — рейтинг книг за кількістю видач (
GROUP BY+COUNT+ORDER BY) - Add book — додавання книги; автор створюється автоматично, якщо ще не існує; жанр/видавництво/рік/ISBN — необов'язкові
- Add reader — додавання читача з категорією (школяр, студент, дошкільник, науковець), кожна з власним набором полів
- Add visit — реєстрація видачі книги через випадаючі списки наявних читачів, бібліотек і книг
- Exit — вихід із системи
- Information about libraries — перелік усіх бібліотек фонду
- Information about librarians — перелік бібліотекарів з прив'язкою до бібліотеки та графіком роботи
- Add user — створення облікового запису (логін, пароль, роль); для бібліотекаря додатково — ПІБ, бібліотека, графік роботи
- System statistics — статистика по всіх таблицях + хвіст
log.txt - Log out — вихід із системи
Увесь UI малюється в окремому Swing-вікні (аналог ftxui з C++ версії): кольорові рамки, кнопки, прокручувані списки. Вибір пункту меню чи кнопки роботить трьома рівноцінними способами:
- стрілками ↑ / ↓ +
Enter; - клавішею
Tabдля переходу між полями; - мишею — реалізовано власним мостом між реальними AWT-подіями миші та внутрішнім механізмом синтетичного вводу Lanterna (
LanternaScreens.installMouseSupport), оскільки стандартний Swing-бекенд Lanterna сам по собі ні кліки, ні рух миші не генерує. Сірий фон поточного пункту тепер рухається за курсором під час наведення (mouseMoved→MouseActionType.MOVE), а не тільки після кліку — так само, як він рухається стрілками; клік (mousePressed/mouseReleased) додатково одразу підтверджує вибір, якEnter.
- Авторизація з розмежуванням прав доступу — роль (
admin/librarian) визначається запитом до БД, і система формує відповідне меню - Обмеження часу доступу (Proxy) — вхід дозволений лише з 07:00 до 16:00; поза цим вікном спроба входу відхиляється й фіксується в журналі
- JOIN-запити до БД — усі звітні розділи будуються на
JOINкількох пов'язаних таблиць - Автоматичне збереження результатів — вивід будь-якого звітного запиту записується у файл (
output.txt/statistics.txt) і одразу відкривається в текстовому редакторі за замовчуванням (Notepad на Windows) - Журналювання дій системи — усі ключові події фіксуються з таймстампом у
log.txtчерезSingleton Logger - Транзакційні багатокрокові вставки — додавання книги/читача/бібліотекаря виконується в одній транзакції з відкатом при помилці
- Розширюваність на інші СУБД — доступ до БД абстраговано через
Abstract Factory(IDBFactory,IDBConnect,IDBOutput)
mvn testПокриття: Logger (Singleton, потокобезпека), AuthorizationProxy (межі вікна 07:00–16:00), PostgresConnection (переходи стану з'єднання), ResultAdapter/PostgresOutput (конвертація й вирівняний вивід у файл), MenuCreator/AdminMenu/LibrarianMenu (маршрутизація за роллю), ApplicationCoordinator (повний цикл вхід → меню → вихід), MainFeatures/ExtendFeatures (SQL, транзакції, дропдауни, валідація вводу), ConsoleUtils (навігація стрілками/Tab/мишею через DefaultVirtualTerminal), LanternaScreens (чиста математика перетворення піксель→комірка, що лежить в основі кліку й наведення мишею — LanternaScreensTest), а також окремий MouseHoverSelectionTest, що підтверджує на рівні самого Lanterna: подія наведення (MouseActionType.MOVE) переводить фокус і рухає виділення на пункт під курсором так само, як стрілки.
| Роль | Доступ |
|---|---|
| admin | Бібліотеки, бібліотекарі, реєстрація користувачів, системна статистика |
| librarian | Книги, читачі, відвідування, найпопулярніші книги, додавання нових записів |
Вхід дозволений лише з 07:00 до 16:00 — навмисне обмеження (AuthorizationProxy), а не помилка застосунку.
Цей проєкт ліцензовано під MIT License. Детальніше дивіться у файлі LICENSE.