Export Guide - nicho92/MtgDesktopCompanion GitHub Wiki

Card Import / Export Module

This page documents the card import/export module used by MTG Desktop Companion to move decks, card search results, alerts, and stock entries between MTG Companion and external tools, marketplaces, clipboard formats, web endpoints, and files.

Purpose

The module is implemented as the MTGCardsExport plugin family. Import/export plugins give MTG Companion a shared contract for:

  • exporting a deck (MTGDeck) to a destination file or external destination;
  • exporting stock rows (List<MTGCardStock>) to a destination file or external destination;
  • importing a deck from a file or raw text payload;
  • importing stock rows from a file or raw text payload;
  • declaring whether the plugin imports, exports, or supports both directions;
  • declaring the target category so UI menus can group providers consistently.

The plugin registry loads this family from org.magic.api.exports.impl under the /deckexports configuration area.

Alias configuration

All import/export plugins inherit the aliases helper from AbstractMTGPlugin. That field is a shared PluginsAliasesProvider instance and should be the first place to put provider-specific translations that are likely to change outside the Java code.

PluginsAliasesProvider reads pluginAliases.json by plugin display name. By default it loads the online copy configured by MTGConstants.MTG_DESKTOP_ALIASES_URL; the bundled resource at src/main/resources/data/pluginsAliases.json is the local copy used when local aliases are enabled. In practice, this means import/export plugins can be adjusted for third-party format changes by updating alias data instead of rebuilding parser logic.

For card import/export providers, pluginAliases.json is intended to hold:

Alias block Direction Used for Helper methods
regex Import/parsing Provider line formats, CSV layouts, deck rows, stock rows, sideboard markers, and named variants such as default, deck, stock, or collection. aliases.getRegexFor(this, key)
conditions Import and export Conversion between EnumCondition values and provider condition labels. aliases.getConditionFor(...), aliases.getReversedConditionFor(...)
idSet Import and export Conversion between MTG Companion set codes and provider-specific set ids. aliases.getSetIdFor(...), aliases.getReversedSetIdFor(...)
nameSet Import and export Conversion between MTG Companion set names and provider-specific set names. aliases.getSetNameFor(...), aliases.getReversedSetNameFor(...)

Best practice for import/export providers is to keep regexes and enum/string conversions in pluginAliases.json whenever possible. Java code should call the helper methods from aliases and only keep structural parsing logic, object creation, and provider workflow code in the provider class. This keeps online marketplace/application naming changes, condition labels, and file-layout regex changes in configuration rather than hard-coded Java constants.

A typical entry looks like this:

{
  "Provider Display Name": {
    "regex": {
      "default": "...",
      "stock": "...",
      "deck": "..."
    },
    "conditions": {
      "NEAR_MINT": "Near Mint",
      "LIGHTLY_PLAYED": "Lightly Played"
    },
    "idSet": {
      "DOM": "DAR"
    },
    "nameSet": {
      "The List": "Mystery Booster/The List"
    }
  }
}

The top-level key must match getName() for the plugin because PluginsAliasesProvider looks up data with plug.getName().

Main concepts

Plugin contract

Every card import/export provider implements MTGCardsExport. The contract exposes these capability groups:

Capability Methods Notes
Deck file type getDeckFileExtension() Defaults to the stock extension in AbstractCardExport unless overridden.
Stock file type getStockFileExtension() Used by file choosers and export target names.
Deck export exportDeck(MTGDeck deck, File dest) Writes or sends a deck.
Stock export exportStock(List<MTGCardStock> stock, File f) Writes or sends stock entries.
Deck import importDeckFromFile(File f), importDeck(String content, String name) Reads a deck from a file or content string.
Stock import importStockFromFile(File f), importStock(String content) Reads stock entries from a file or content string.
Destination mode needFile() true for file-backed providers, false for clipboard, online, or dialog-only flows.
Optional dialogs needDialogForDeck(MODS mod), needDialogForStock(MODS mod) Allows providers to open custom import/export UI instead of a simple file chooser.
Category getCategory() Groups menu entries as file, application, external format, online, manual, MTG Companion, or none.
Direction getMods() Returns IMPORT, EXPORT, or BOTH.

Direction modes

MTGCardsExport.MODS controls whether a provider appears in import menus, export menus, or both:

  • IMPORT — reads external content into MTG Companion.
  • EXPORT — sends MTG Companion content to an external format or target.
  • BOTH — supports both import and export.

AbstractCardExport returns BOTH by default, so export-only or import-only providers must override getMods().

Categories

Providers use EnumExportCategory to drive categorized UI menus:

Category Typical use
FILE Generic local file formats.
EXTERNAL_FILE_FORMAT Files shaped for websites or third-party tools.
APPLICATION Application-specific formats such as MTGO, Forge, XMage, or Arena.
ONLINE Providers that communicate with online services or import from URLs.
MANUAL Clipboard, webcam, manual paste, or dialog-driven flows.
MTGCOMPANION MTG Companion native interchange data.
NONE Providers that should not be visually grouped as a normal destination.

Runtime flow

Desktop deck import

  1. The deck construction panel builds an import menu from enabled MTGCardsExport plugins.
  2. Providers are filtered to IMPORT or BOTH.
  3. If the provider needs a file and no custom dialog is required, a file chooser is opened with the provider deck extension.
  4. The selected file is processed by DeckImportWorker, which calls importDeckFromFile in the background.
  5. When the worker finishes, the imported MTGDeck replaces the current deck in the construction panel.

Desktop deck/card/alert export

  1. JExportButton builds an export menu from enabled providers.
  2. Providers are filtered to EXPORT or BOTH.
  3. If the provider needs a file, a save dialog is created using the provider file extension.
  4. Deck and card-list exports run through CardExportWorker, which calls exportDeck.
  5. Alert exports are converted to a temporary deck-like list of one-copy cards before export.

Desktop stock export

  1. JExportButton.initStockExport builds the same categorized export menu.
  2. Providers are filtered to EXPORT or BOTH.
  3. File-backed providers receive a stocks<extension> save target.
  4. StockExportWorker calls exportStock in the background.

JSON HTTP import/export

When the JSON HTTP server is enabled, the module also exposes lightweight routes:

Route Method Behavior
/cards/import/:provider POST Reads the request body and calls the named MTGCardsExport provider's importDeck(content, "webimport").
/deck/export/:provider/:idDeck GET Loads a deck by id, exports it with the named provider to a temporary file, then returns either file text or binary image content.

The Swagger file documents /cards/import/{provider} as the endpoint for importing deck/card content through a provider.

Base classes

AbstractCardExport

Most providers extend AbstractCardExport, which provides defaults and adapters:

  • plugin type is EXPORT;
  • getMods() defaults to BOTH;
  • needFile() defaults to true;
  • deck and stock extensions are shared unless the provider overrides getDeckFileExtension();
  • default category is FILE for file-backed providers, otherwise NONE;
  • default dialog requirements are false;
  • deck import/export can be adapted through stock import/export and vice versa;
  • imported deck cards are converted to default MTGCardStock rows with quantity, product, comment, and update flags.

AbstractFormattedFileCardExport

Formatted file providers can extend AbstractFormattedFileCardExport to reuse common parsing behavior:

  • split content into lines and optionally skip the first line;
  • skip lines with provider-specific prefixes;
  • match each line with a provider regex;
  • resolve editions by set id or name aliases from pluginAliases.json;
  • resolve cards by card id, name, or collector number;
  • read regex patterns through aliases.getRegexFor(this, key) instead of hard-coding format regexes;
  • expose a configurable SEPARATOR property.

Adding a new provider

  1. Create a class in src/main/java/org/magic/api/exports/impl.
  2. Extend AbstractCardExport for general providers or AbstractFormattedFileCardExport for regex/line-based formats.
  3. Implement at minimum:
    • getName();
    • getStockFileExtension();
    • exportDeck and/or exportStock if the provider exports;
    • importDeck, importDeckFromFile, importStock, and/or importStockFromFile if the provider imports.
  4. Override getMods() for import-only or export-only providers.
  5. Override getCategory() when the default FILE category is not appropriate.
  6. Override needFile() for clipboard, online, or dialog-only flows.
  7. Override needDialogForDeck or needDialogForStock when the provider needs custom user input.
  8. Add or update the provider entry in src/main/resources/data/pluginsAliases.json for regex patterns, condition conversions, and set id/name aliases.
  9. If the parser is line-based, define skipFirstLine(), skipLinesStartWith(), getSeparator(), and consume regex/alias behavior through AbstractFormattedFileCardExport.
  10. Run the export provider test suite to exercise the plugin through both deck and stock paths.

Validation checklist

Before shipping a provider or changing an existing one:

  • The provider appears in the expected import/export menu only.
  • The menu category matches the destination type.
  • File chooser filters use the expected deck and stock extensions.
  • Importers resolve cards through the enabled MTGCardsProvider.
  • Regexes, condition labels, and set aliases are configured through pluginAliases.json instead of hard-coded in provider classes.
  • Exporters preserve quantities and sideboard/mainboard behavior when the format supports it.
  • Non-file providers return needFile() == false and handle a null destination safely.
  • Long-running import/export work reports observer progress where practical.
  • ExportsProviderTests runs without new provider failures.

Related source files

  • src/main/java/org/magic/api/interfaces/MTGCardsExport.java — plugin interface and mode enum.
  • src/main/java/org/magic/api/interfaces/abstracts/AbstractMTGPlugin.java — base plugin class that exposes the shared aliases provider.
  • src/main/java/org/magic/api/interfaces/abstracts/AbstractCardExport.java — default adapters for deck and stock import/export.
  • src/main/java/org/magic/api/interfaces/abstracts/extra/AbstractFormattedFileCardExport.java — helpers for formatted text/CSV-like providers.
  • src/main/java/org/magic/api/beans/enums/EnumExportCategory.java — provider category enum.
  • src/main/java/org/magic/api/exports/impl — provider implementations.
  • src/main/java/org/magic/services/providers/PluginsAliasesProvider.java — loader and accessor for provider alias data.
  • src/main/resources/data/pluginsAliases.json — bundled alias configuration for regexes, conditions, set ids, and set names.
  • src/main/java/org/magic/gui/components/widgets/JExportButton.java — reusable desktop export menu button.
  • src/main/java/org/magic/gui/components/deck/ConstructPanel.java — desktop deck import/export integration.
  • src/main/java/org/magic/services/workers/CardExportWorker.java — background deck/card export worker.
  • src/main/java/org/magic/services/workers/StockExportWorker.java — background stock export worker.
  • src/main/java/org/magic/services/workers/DeckImportWorker.java — background deck import worker.
  • src/main/java/org/magic/servers/impl/JSONHttpServer.java — JSON HTTP import/export routes.
  • docs/swagger-jsonhttpserver.yaml — JSON HTTP API documentation.
  • src/test/java/test/providers/ExportsProviderTests.java — provider smoke tests.
⚠️ **GitHub.com Fallback** ⚠️