Developer Guide - nicho92/MtgDesktopCompanion GitHub Wiki
This document explains the project architecture, the global business logic, and especially the role of interfaces and abstract classes to help developers ramp up quickly.
MTG Desktop Companion is a desktop-oriented Java monolith (Swing) with embedded services (web/API/jobs) and a strongly plugin-oriented architecture.
Main layers:
-
Entry point / bootstrap (
org.magic.main): startup sequence, splash screen, config/plugin loading, GUI startup. -
Core services (
org.magic.services): global configuration, plugin registry, threading, i18n, cross-cutting tools. -
API contracts (
org.magic.api.interfaces): business interfaces for each plugin family. -
Implementation skeletons (
org.magic.api.interfaces.abstracts): abstract classes with shared default behavior. -
Concrete implementations (
org.magic.api.*.impl): providers/pricers/DAO/exporters/etc. -
UI (
org.magic.gui): Swing interface. -
Servers (
org.magic.servers.impl) : embedded servers
Desktop startup runs through MtgDesktopCompanion.main().
Simplified flow:
- Logger and splash initialization.
- Configuration loading through
MTGControler(singleton). -
MTGControlerwiresPluginRegistrywith XML configuration. - Key plugins are loaded/activated (cards provider + DAO).
- Main GUI (
MagicGUI) is shown. - Enabled
MTGServerplugins withautostartare started.
👉 In practice, configuration drives everything: active plugins, options, accounts, thread pool, and more.
MTGPlugin is the root interface of almost the entire plugin ecosystem.
Main responsibilities:
- lifecycle:
load(),save(),unload(),enable(boolean); - metadata:
getName(),getType(),getVersion(),getStatut(); - configuration:
getProperties(),setProperty(),getDefaultAttributes(); - observability:
addObserver(),removeObserver(), etc.; - security/account integration:
needAuthenticator(),getAuthenticator().
The MTGPlugin.PLUGINS enum includes:
-
PROVIDER,PRICER,DAO,SERVER,EXPORT,NEWS,PICTURE, -
CACHE,TOKEN,SCRIPT,POOL,COMBO,GRADING, -
TRACKING,EXTERNAL_SHOP,IA,SEALED,NETWORK, and more.
This enum is used both for runtime organization and XML configuration mapping.
AbstractMTGPlugin provides common mechanics:
- plugin config file management (
<conf_dir>/<type>/<plugin>.conf); - property loading/saving;
-
enabled/loadedstate handling; - icon/documentation/observer notifications;
- default behavior shared by most plugin types.
➡️ In most cases, a new plugin should extend a specialized abstract class, which itself extends AbstractMTGPlugin.
PluginRegistry acts as the lightweight plugin container.
It:
- declares all plugin families (
init()); - maps interface ↔ implementation package ↔ XML paths;
- dynamically instantiates classes through reflection;
- loads configured plugins;
- handles missing/incompatible plugins by cleaning config entries.
The static helper MTG simplifies usage from the rest of the app:
-
getEnabledPlugin(MyType.class); -
listEnabledPlugins(MyType.class); -
getPlugin("Name", MyType.class).
The project follows a very consistent pattern:
- 1 business interface per domain,
- 1 base abstract class with shared behavior,
- N concrete implementations.
Core examples:
-
MTGCardsProvider→AbstractCardsProvider→ concrete providers (Scryfall, etc.). -
MTGPricesProvider→AbstractPricesProvider→ multi-source pricers. -
MTGDao→AbstractMagicDAO(+AbstractMagicSQLDAO) → SQL/file DAO backends. -
MTGServer→AbstractMTGServer(+AbstractWebServer/AbstractWarServer) → embedded servers. -
MTGCardsExport→AbstractCardExport(+AbstractFormattedFileCardExport) → multi-format exports.
-
AbstractCardsProvider: cards/editions/languages cache, query helpers, booster generation. -
AbstractPricesProvider: price normalization + currency conversion + best-price selection. -
AbstractMagicDAO: cross-cutting utility operations (stocks, collections, duplication, announcements). -
AbstractMTGServer: embedded server cache + default timeout attributes.
Important consequence: Most horizontal business logic lives in abstract classes; concrete implementations mostly focus on external source integration (API/site/DB/file).
-
src/main/java/org/magic/main: executable entry points (desktop, server launcher, scripts UI). -
src/main/java/org/magic/services: technical core and orchestration. -
src/main/java/org/magic/api/interfaces: plugin contracts. -
src/main/java/org/magic/api/interfaces/abstracts: base implementation skeletons. -
src/main/java/org/magic/api/*/impl: domain implementations. -
src/main/java/org/magic/servers/impl: embedded server implementations. -
src/main/resources: default configs, assets, web UIs, i18n. -
src/test/java: unit/integration tests by provider domain.
MTGControler is the runtime singleton:
- creates/loads
default-conf.xml; - initializes i18n (
LanguageService), LAF, and thread pool; - configures
PluginRegistry; - manages cross-cutting services (currency converter, webshop, version checker).
It effectively acts as a historical application service locator.
Primary storage is handled by the active MTGDao plugin.
AbstractMagicDAO already provides high-level behavior (stocks, announcements, collections, DAO-to-DAO duplication), reducing backend-specific boilerplate.
The application integrates many connectors:
- card/price/image/news providers,
- exporters to external formats/platforms,
- parcel tracking, external shops, AI providers, etc.
Each connector remains interchangeable because it is constrained by a dedicated plugin interface.
MTGServer plugins expose embedded network capabilities (JSON API, admin dashboards, shopping/trades web UI, scheduled jobs, monitoring), with optional autostart.
- Identify the family (
MTGPricesProvider,MTGNewsProvider, etc.). - Extend the matching abstract class.
- Implement only the required abstract business methods.
- Declare config attributes with
getDefaultAttributes(). - Add focused tests under
src/test/java/test/providers/....
If no existing family fits:
- Create a new interface in
org.magic.api.interfaces. - Create a dedicated abstract base class in
...interfaces.abstracts. - Register the new family in
PluginRegistry.init(). - Add any required UI/config integration.
To understand the project quickly, follow this order:
-
README.md(global vision + build) -
MtgDesktopCompanion(real bootstrap) -
MTGControler(config/runtime) -
PluginRegistry+MTGPlugin+AbstractMTGPlugin - One full interface→abstract→implementation chain (for example pricer)
- Tests in your target domain
- Plugin-first architecture.
-
MTGPlugin= universal contract. -
AbstractMTGPlugin= shared technical foundation. - Specialized abstract classes already contain most shared business logic.
- Concrete implementations are mostly adapters to external sources.
-
PluginRegistry+MTGControlerorchestrate the runtime.
This is a mature, extensible base with a significant initial discovery cost (many modules), but strong functional scalability once the pattern is understood.
See Plugins-Guide for more details about plugins