diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java
index 182be367ebd..ad61e89d849 100644
--- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java
+++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java
@@ -14,7 +14,6 @@ import mage.cards.Sets;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckCardLists;
import mage.cards.decks.importer.DeckImporter;
-import mage.cards.decks.importer.DeckImporterUtil;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.client.MageFrame;
@@ -798,7 +797,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
- newDeck = Deck.load(DeckImporterUtil.importDeck(dialog.getTmpPath(), errorMessages), true, true);
+ newDeck = Deck.load(DeckImporter.importDeckFromFile(dialog.getTmpPath(), errorMessages), true, true);
processAndShowImportErrors(errorMessages);
if (newDeck != null) {
@@ -831,7 +830,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
- deckToAppend = Deck.load(DeckImporterUtil.importDeck(dialog.getTmpPath(), errorMessages), true, true);
+ deckToAppend = Deck.load(DeckImporter.importDeckFromFile(dialog.getTmpPath(), errorMessages), true, true);
processAndShowImportErrors(errorMessages);
if (deckToAppend != null) {
@@ -878,7 +877,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
Deck newDeck = null;
StringBuilder errorMessages = new StringBuilder();
- newDeck = Deck.load(DeckImporterUtil.importDeck(file.getPath(), errorMessages), true, true);
+ newDeck = Deck.load(DeckImporter.importDeckFromFile(file.getPath(), errorMessages), true, true);
processAndShowImportErrors(errorMessages);
if (newDeck != null) {
@@ -977,7 +976,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
File file = fcImportDeck.getSelectedFile();
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
- DeckImporter importer = DeckImporterUtil.getDeckImporter(file.getPath());
+ DeckImporter importer = DeckImporter.getDeckImporter(file.getPath());
if (importer != null) {
StringBuilder errorMessages = new StringBuilder();
@@ -1048,7 +1047,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
try {
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
String path = DeckGenerator.generateDeck();
- deck = Deck.load(DeckImporterUtil.importDeck(path), true, true);
+ deck = Deck.load(DeckImporter.importDeckFromFile(path), true, true);
} catch (GameException ex) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Error loading generated deck", JOptionPane.ERROR_MESSAGE);
} catch (DeckGeneratorException ex) {
@@ -1120,7 +1119,11 @@ class ImportFilter extends FileFilter {
ext = s.substring(i + 1).toLowerCase(Locale.ENGLISH);
}
if (ext != null) {
- if (ext.toLowerCase(Locale.ENGLISH).equals("dec") || ext.toLowerCase(Locale.ENGLISH).equals("mwdeck") || ext.toLowerCase(Locale.ENGLISH).equals("txt") || ext.toLowerCase(Locale.ENGLISH).equals("dek")) {
+ if (ext.toLowerCase(Locale.ENGLISH).equals("dec")
+ || ext.toLowerCase(Locale.ENGLISH).equals("mwdeck")
+ || ext.toLowerCase(Locale.ENGLISH).equals("txt")
+ || ext.toLowerCase(Locale.ENGLISH).equals("dek")
+ || ext.toLowerCase(Locale.ENGLISH).equals("cod")) {
return true;
}
}
@@ -1129,7 +1132,7 @@ class ImportFilter extends FileFilter {
@Override
public String getDescription() {
- return "*.dec | *.mwDeck | *.txt | *.dek";
+ return "*.dec | *.mwDeck | *.txt | *.dek | *.cod";
}
}
diff --git a/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java
index a16a7bbccd0..5d4e19e7642 100644
--- a/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java
+++ b/Mage.Client/src/main/java/mage/client/dialog/JoinTableDialog.java
@@ -1,7 +1,7 @@
package mage.client.dialog;
-import mage.cards.decks.importer.DeckImporterUtil;
+import mage.cards.decks.importer.DeckImporter;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.players.PlayerType;
@@ -119,9 +119,9 @@ public class JoinTableDialog extends MageDialog {
try {
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_PASSWORD_JOIN, txtPassword.getText());
if (isTournament) {
- joined = session.joinTournamentTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporterUtil.importDeck(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText());
+ joined = session.joinTournamentTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText());
} else {
- joined = session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporterUtil.importDeck(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText());
+ joined = session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText());
}
} catch (Exception ex) {
diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java
index c47059ed798..e4ad14fbaef 100644
--- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java
+++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java
@@ -7,7 +7,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.swing.*;
-import mage.cards.decks.importer.DeckImporterUtil;
+
+import mage.cards.decks.importer.DeckImporter;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.components.MageComponents;
@@ -425,7 +426,7 @@ public class NewTableDialog extends MageDialog {
table.getTableId(),
this.player1Panel.getPlayerName(),
PlayerType.HUMAN, 1,
- DeckImporterUtil.importDeck(this.player1Panel.getDeckFile()),
+ DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()),
this.txtPassword.getText())) {
for (TablePlayerPanel player : players) {
if (player.getPlayerType() != PlayerType.HUMAN) {
diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java
index fef9bdab407..bba0ef95006 100644
--- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java
+++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java
@@ -18,7 +18,7 @@ import java.util.UUID;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import mage.cards.decks.Deck;
-import mage.cards.decks.importer.DeckImporterUtil;
+import mage.cards.decks.importer.DeckImporter;
import mage.cards.repository.ExpansionInfo;
import mage.cards.repository.ExpansionRepository;
import mage.client.MageFrame;
@@ -557,7 +557,7 @@ public class NewTournamentDialog extends MageDialog {
if (!(cubeFromDeckFilename.isEmpty())) {
Deck cubeFromDeck = new Deck();
try {
- cubeFromDeck = Deck.load(DeckImporterUtil.importDeck(cubeFromDeckFilename), true, true);
+ cubeFromDeck = Deck.load(DeckImporter.importDeckFromFile(cubeFromDeckFilename), true, true);
} catch (GameException e1) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE);
}
@@ -631,11 +631,11 @@ public class NewTournamentDialog extends MageDialog {
table.getTableId(),
this.player1Panel.getPlayerName(),
PlayerType.HUMAN, 1,
- DeckImporterUtil.importDeck(this.player1Panel.getDeckFile()),
+ DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()),
tOptions.getPassword())) {
for (TournamentPlayerPanel player : players) {
if (player.getPlayerType().getSelectedItem() != PlayerType.HUMAN) {
- if (!player.joinTournamentTable(roomId, table.getTableId(), DeckImporterUtil.importDeck(this.player1Panel.getDeckFile()))) {
+ if (!player.joinTournamentTable(roomId, table.getTableId(), DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()))) {
// error message must be send by sever
SessionHandler.removeTable(roomId, table.getTableId());
table = null;
diff --git a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java
index 42541329f91..57ced4260ea 100644
--- a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java
@@ -20,7 +20,8 @@ import javax.swing.JPopupMenu;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.MenuSelectionManager;
import javax.swing.event.ChangeListener;
-import mage.cards.decks.importer.DeckImporterUtil;
+
+import mage.cards.decks.importer.DeckImporter;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.cards.BigCard;
@@ -569,7 +570,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
}
private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) {
- SessionHandler.cheat(gameId, playerId, DeckImporterUtil.importDeck("cheat.dck"));
+ SessionHandler.cheat(gameId, playerId, DeckImporter.importDeckFromFile("cheat.dck"));
}
public boolean isSmallMode() {
diff --git a/Mage.Client/src/main/java/mage/client/table/TablePlayerPanel.java b/Mage.Client/src/main/java/mage/client/table/TablePlayerPanel.java
index d18df6ef694..99d0dae1098 100644
--- a/Mage.Client/src/main/java/mage/client/table/TablePlayerPanel.java
+++ b/Mage.Client/src/main/java/mage/client/table/TablePlayerPanel.java
@@ -8,7 +8,7 @@
package mage.client.table;
-import mage.cards.decks.importer.DeckImporterUtil;
+import mage.cards.decks.importer.DeckImporter;
import mage.client.SessionHandler;
import mage.client.util.Config;
import mage.client.util.Event;
@@ -53,7 +53,7 @@ public class TablePlayerPanel extends javax.swing.JPanel {
public boolean joinTable(UUID roomId, UUID tableId) throws IOException, ClassNotFoundException {
if (this.cbPlayerType.getSelectedItem() != PlayerType.HUMAN) {
- return SessionHandler.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), (PlayerType) this.cbPlayerType.getSelectedItem(), this.newPlayerPanel.getLevel(), DeckImporterUtil.importDeck(this.newPlayerPanel.getDeckFile()), "");
+ return SessionHandler.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), (PlayerType) this.cbPlayerType.getSelectedItem(), this.newPlayerPanel.getLevel(), DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile()), "");
}
return true;
}
diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java
index 7bbd6816add..7652a5040b5 100644
--- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java
+++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java
@@ -1,6 +1,6 @@
package mage.client.table;
-import mage.cards.decks.importer.DeckImporterUtil;
+import mage.cards.decks.importer.DeckImporter;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.chat.ChatPanelBasic;
@@ -1263,8 +1263,8 @@ public class TablesPanel extends javax.swing.JPanel {
options.setBannedUsers(IgnoreList.ignoreList(serverAddress));
table = SessionHandler.createTable(roomId, options);
- SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, DeckImporterUtil.importDeck("test.dck"), "");
- SessionHandler.joinTable(roomId, table.getTableId(), "Computer", PlayerType.COMPUTER_MAD, 5, DeckImporterUtil.importDeck("test.dck"), "");
+ SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile("test.dck"), "");
+ SessionHandler.joinTable(roomId, table.getTableId(), "Computer", PlayerType.COMPUTER_MAD, 5, DeckImporter.importDeckFromFile("test.dck"), "");
SessionHandler.startMatch(roomId, table.getTableId());
} catch (HeadlessException ex) {
handleError(ex);
diff --git a/Mage.Client/src/test/java/mage/cards/decks/importer/CodDeckImportTest.java b/Mage.Client/src/test/java/mage/cards/decks/importer/CodDeckImportTest.java
new file mode 100644
index 00000000000..6e2c9993174
--- /dev/null
+++ b/Mage.Client/src/test/java/mage/cards/decks/importer/CodDeckImportTest.java
@@ -0,0 +1,44 @@
+package mage.cards.decks.importer;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import mage.cards.decks.DeckCardInfo;
+import mage.cards.decks.DeckCardLists;
+
+public class CodDeckImportTest {
+
+ @Test
+ public void testImportCod() {
+ StringBuilder errors = new StringBuilder();
+ DeckCardLists deck = new CodDeckImporter().importDeck(
+ "src/test/java/mage/cards/decks/importer/testdeck.cod", errors);
+ assertEquals("Deck Name", deck.getName());
+ assertEquals(113, deck.getCards().size());
+ assertEquals(3, deck.getSideboard().size());
+ int index = 0;
+ for (int i = 0; i < 12; i++) {
+ assertCardSame("Forest", deck.getCards().get(index++));
+ }
+ for (int i = 0; i < 100; i++) {
+ assertCardSame("Razorverge Thicket", deck.getCards().get(index++));
+ }
+ assertCardSame("Avacyn's Pilgrim", deck.getCards().get(index++));
+ assertEquals(index, deck.getCards().size());
+
+ index = 0;
+ for (int i = 0; i < 3; i++) {
+ assertCardSame("War Priest of Thune", deck.getSideboard().get(index++));
+ }
+ assertEquals(index, deck.getSideboard().size());
+
+ assertEquals("Could not find card: '@#$NOT A REAL CARD NAME@#$'\n", errors.toString());
+ }
+
+ private static void assertCardSame(String name, DeckCardInfo card) {
+ assertEquals(name, card.getCardName());
+ assertEquals(1, card.getQuantity());
+ }
+
+}
diff --git a/Mage.Client/src/test/java/mage/cards/decks/importer/DecDeckImportTest.java b/Mage.Client/src/test/java/mage/cards/decks/importer/DecDeckImportTest.java
new file mode 100644
index 00000000000..0cefeecc72d
--- /dev/null
+++ b/Mage.Client/src/test/java/mage/cards/decks/importer/DecDeckImportTest.java
@@ -0,0 +1,20 @@
+package mage.cards.decks.importer;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import mage.cards.decks.DeckCardLists;
+
+public class DecDeckImportTest {
+
+ @Test
+ public void testImport() {
+ StringBuilder errors = new StringBuilder();
+ DeckCardLists deck = new DecDeckImporter().importDeck(
+ "src/test/java/mage/cards/decks/importer/testdeck.dec", errors);
+ assertEquals(60, deck.getCards().size());
+ assertEquals(15, deck.getSideboard().size());
+ }
+
+}
diff --git a/Mage.Client/src/test/java/mage/cards/decks/importer/testdeck.cod b/Mage.Client/src/test/java/mage/cards/decks/importer/testdeck.cod
new file mode 100644
index 00000000000..c90d63f6767
--- /dev/null
+++ b/Mage.Client/src/test/java/mage/cards/decks/importer/testdeck.cod
@@ -0,0 +1,14 @@
+
+
+ Deck Name
+ Some comments in here.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Mage.Client/src/test/java/mage/cards/decks/importer/testdeck.dec b/Mage.Client/src/test/java/mage/cards/decks/importer/testdeck.dec
new file mode 100644
index 00000000000..80abb81381d
--- /dev/null
+++ b/Mage.Client/src/test/java/mage/cards/decks/importer/testdeck.dec
@@ -0,0 +1,28 @@
+// Name: Mono-Blue Tinker from MTGSalvation.com via mtgtrice mtg-decks
+// Creatures
+ 4 Masticore
+ 4 Metalworker
+ 1 Phyrexian Colossus
+// Artifacts
+ 1 Crumbling Sanctuary
+ 4 Grim Monolith
+ 1 Mishra's Helix
+ 4 Phyrexian Processor
+ 4 Tangle Wire
+ 4 Thran Dynamo
+ 4 Voltaic Key
+// Sorceries
+ 4 Tinker
+// Instants
+ 4 Brainstorm
+// Lands
+ 4 Crystal Vein
+ 9 Island
+ 4 Rishadan Port
+ 4 Saprazzan Skerry
+// Sideboard
+SB: 4 Annul
+SB: 4 Chill
+SB: 4 Miscalculation
+SB: 1 Mishra's Helix
+SB: 2 Rising Waters
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
index 4c18ad006f2..68a3ea860d7 100644
--- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
@@ -6,7 +6,7 @@ import mage.abilities.Ability;
import mage.cards.Card;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckCardLists;
-import mage.cards.decks.importer.DeckImporterUtil;
+import mage.cards.decks.importer.DeckImporter;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.cards.repository.CardScanner;
@@ -189,7 +189,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
if (loadedDeckCardLists.containsKey(deckName)) {
list = loadedDeckCardLists.get(deckName);
} else {
- list = DeckImporterUtil.importDeck(deckName);
+ list = DeckImporter.importDeckFromFile(deckName);
loadedDeckCardLists.put(deckName, list);
}
Deck deck = Deck.load(list, false, false);
diff --git a/Mage/src/main/java/mage/cards/decks/importer/CodDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/CodDeckImporter.java
new file mode 100644
index 00000000000..8ef40a0619c
--- /dev/null
+++ b/Mage/src/main/java/mage/cards/decks/importer/CodDeckImporter.java
@@ -0,0 +1,116 @@
+package mage.cards.decks.importer;
+
+import static javax.xml.xpath.XPathConstants.NODESET;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+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;
+import org.xml.sax.SAXException;
+
+import mage.cards.decks.DeckCardInfo;
+import mage.cards.decks.DeckCardLists;
+import mage.cards.repository.CardInfo;
+import mage.cards.repository.CardRepository;
+
+public class CodDeckImporter extends DeckImporter {
+
+ private XPathFactory xpathFactory = XPathFactory.newInstance();
+ private DocumentBuilder builder = getDocumentBuilder();
+
+ @Override
+ public DeckCardLists importDeck(String filename, StringBuilder errorMessages) {
+ try {
+ Document doc = getXmlDocument(filename);
+ DeckCardLists decklist = new DeckCardLists();
+
+ List mainCards = getNodes(doc, "/cockatrice_deck/zone[@name='main']/card");
+ decklist.setCards(mainCards.stream()
+ .flatMap(toDeckCardInfo(errorMessages))
+ .collect(Collectors.toList()));
+
+ List sideboardCards = getNodes(doc, "/cockatrice_deck/zone[@name='side']/card");
+ decklist.setSideboard(sideboardCards.stream()
+ .flatMap(toDeckCardInfo(errorMessages))
+ .collect(Collectors.toList()));
+
+ getNodes(doc, "/cockatrice_deck/deckname")
+ .forEach(n -> decklist.setName(n.getTextContent().trim()));
+
+ return decklist;
+ } catch (Exception e) {
+ logger.error("Error loading deck", e);
+ errorMessages.append("There was an error loading the deck.");
+ return new DeckCardLists();
+ }
+ }
+
+ private static int getQuantityFromNode(Node node) {
+ Node numberNode = node.getAttributes().getNamedItem("number");
+ if (numberNode == null) {
+ return 1;
+ }
+ try {
+ return Math.min(100, Math.max(0, Integer.parseInt(numberNode.getNodeValue())));
+ } catch (NumberFormatException e) {
+ return 1;
+ }
+ }
+
+ private static Function> toDeckCardInfo(StringBuilder errors) {
+ return node -> {
+ String name = node.getAttributes().getNamedItem("name").getNodeValue().trim();
+ CardInfo cardInfo = CardRepository.instance.findPreferedCoreExpansionCard(name, true);
+ if (cardInfo != null) {
+ return Collections.nCopies(
+ getQuantityFromNode(node),
+ new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode()))
+ .stream();
+ } else {
+ errors.append("Could not find card: '").append(name).append("'\n");
+ }
+ return Stream.empty();
+ };
+ }
+
+ private List getNodes(Document doc, String xpathExpression) throws XPathExpressionException {
+ NodeList nodes = (NodeList) xpathFactory.newXPath().evaluate(xpathExpression, doc, NODESET);
+ ArrayList list = new ArrayList<>();
+ for (int i = 0; i < nodes.getLength(); i++) {
+ list.add(nodes.item(i));
+ }
+ return list;
+ }
+
+ private DocumentBuilder getDocumentBuilder() {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ return factory.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException();
+ }
+ }
+
+ protected Document getXmlDocument(String filename) throws IOException {
+ try {
+ return builder.parse(new File(filename));
+ } catch (SAXException e) {
+ throw new IOException(e);
+ }
+ }
+
+}
diff --git a/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java
index fee59b3b4d6..787e3cfe5ac 100644
--- a/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java
+++ b/Mage/src/main/java/mage/cards/decks/importer/DckDeckImporter.java
@@ -15,7 +15,7 @@ import mage.cards.repository.CardRepository;
*
* @author North
*/
-public class DckDeckImporter extends DeckImporter {
+public class DckDeckImporter extends PlainTextDeckImporter {
private static final Pattern pattern = Pattern.compile("(SB:)?\\s*(\\d*)\\s*\\[([^]:]+):([^]:]+)\\]\\s*(.*)\\s*$");
diff --git a/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java
index cf2c83a0c55..94a879ad959 100644
--- a/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java
+++ b/Mage/src/main/java/mage/cards/decks/importer/DecDeckImporter.java
@@ -10,7 +10,7 @@ import mage.cards.repository.CardRepository;
*
* @author BetaSteward_at_googlemail.com
*/
-public class DecDeckImporter extends DeckImporter {
+public class DecDeckImporter extends PlainTextDeckImporter {
@Override
protected void readLine(String line, DeckCardLists deckList) {
diff --git a/Mage/src/main/java/mage/cards/decks/importer/DeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DeckImporter.java
index 1957cd7058e..02c94df04ac 100644
--- a/Mage/src/main/java/mage/cards/decks/importer/DeckImporter.java
+++ b/Mage/src/main/java/mage/cards/decks/importer/DeckImporter.java
@@ -1,74 +1,80 @@
-
-
package mage.cards.decks.importer;
-import mage.cards.decks.DeckCardLists;
import org.apache.log4j.Logger;
-
import java.io.File;
+import java.util.Locale;
import java.util.Scanner;
-/**
- *
- * @author BetaSteward_at_googlemail.com
- */
+
+import mage.cards.decks.DeckCardLists;
+
public abstract class DeckImporter {
- private static final Logger logger = Logger.getLogger(DeckImporter.class);
+ protected static final Logger logger = Logger.getLogger(DeckImporter.class);
- protected StringBuilder sbMessage = new StringBuilder(); //TODO we should stop using this not garbage collectable StringBuilder. It just bloats
- protected int lineCount;
+ private static final String[] SIDEBOARD_MARKS = new String[]{"//sideboard", "sb: "};
+ public static DeckImporter getDeckImporter(String file) {
+ if (file == null) {
+ return null;
+ } if (file.toLowerCase(Locale.ENGLISH).endsWith("dec")) {
+ return new DecDeckImporter();
+ } else if (file.toLowerCase(Locale.ENGLISH).endsWith("mwdeck")) {
+ return new MWSDeckImporter();
+ } else if (file.toLowerCase(Locale.ENGLISH).endsWith("txt")) {
+ return new TxtDeckImporter(haveSideboardSection(file));
+ } else if (file.toLowerCase(Locale.ENGLISH).endsWith("dck")) {
+ return new DckDeckImporter();
+ } else if (file.toLowerCase(Locale.ENGLISH).endsWith("dek")) {
+ return new DekDeckImporter();
+ } else if (file.toLowerCase(Locale.ENGLISH).endsWith("cod")) {
+ return new CodDeckImporter();
+ } else {
+ return null;
+ }
+ }
- /**
- *
- * @param file file to import
- * @param errorMessages you can setup output messages to showup to user (set null for fatal exception on messages.count > 0)
- * @return decks list
- */
- public DeckCardLists importDeck(String file, StringBuilder errorMessages) {
- File f = new File(file);
- DeckCardLists deckList = new DeckCardLists();
- if (!f.exists()) {
- logger.warn("Deckfile " + file + " not found.");
- return deckList;
+ public static DeckCardLists importDeckFromFile(String file) {
+ return importDeckFromFile(file, new StringBuilder());
+ }
+
+ public static DeckCardLists importDeckFromFile(String file, StringBuilder errorMessages) {
+ DeckImporter deckImporter = getDeckImporter(file);
+ if (deckImporter != null) {
+ return deckImporter.importDeck(file, errorMessages);
+ } else {
+ return new DeckCardLists();
+ }
+ }
+
+ public abstract DeckCardLists importDeck(String file, StringBuilder errorMessages);
+
+ public DeckCardLists importDeck(String file) {
+ return importDeck(file, new StringBuilder());
+ }
+
+ private static boolean haveSideboardSection(String file) {
+ // search for sideboard section:
+ // or //sideboard
+ // or SB: 1 card name -- special deckstats.net
+
+ File f = new File(file);
+ try (Scanner scanner = new Scanner(f)) {
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine().trim().toLowerCase(Locale.ENGLISH);
+
+ for (String mark : SIDEBOARD_MARKS) {
+ if (line.startsWith(mark)) {
+ return true;
+ }
}
- lineCount = 0;
-
- sbMessage.setLength(0);
- try {
- try (Scanner scanner = new Scanner(f)) {
- while (scanner.hasNextLine()) {
- String line = scanner.nextLine().trim();
- lineCount++;
- readLine(line, deckList);
- }
-
- if (sbMessage.length() > 0) {
- if(errorMessages != null) {
- // normal output for user
- errorMessages.append(sbMessage);
- }else{
- // fatal error
- logger.fatal(sbMessage);
- }
- }
- } catch (Exception ex) {
- logger.fatal(null, ex);
- }
- } catch (Exception ex) {
- logger.fatal(null, ex);
- }
- return deckList;
+ }
+ } catch (Exception e) {
+ // ignore error, deckimporter will process it
}
- public DeckCardLists importDeck(String file) {
- return importDeck(file, null);
- }
+ // not found
+ return false;
+ }
- public String getErrors(){
- return sbMessage.toString();
- }
-
- protected abstract void readLine(String line, DeckCardLists deckList);
}
diff --git a/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java b/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java
deleted file mode 100644
index 0384a17f44c..00000000000
--- a/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java
+++ /dev/null
@@ -1,71 +0,0 @@
-
-package mage.cards.decks.importer;
-
-import java.io.File;
-import java.util.Locale;
-import java.util.Scanner;
-import mage.cards.decks.DeckCardLists;
-
-/**
- *
- * @author North
- */
-public final class DeckImporterUtil {
-
- private static final String[] SIDEBOARD_MARKS = new String[]{"//sideboard", "sb: "};
-
- public static boolean haveSideboardSection(String file) {
- // search for sideboard section:
- // or //sideboard
- // or SB: 1 card name -- special deckstats.net
-
- File f = new File(file);
- try (Scanner scanner = new Scanner(f)) {
- while (scanner.hasNextLine()) {
- String line = scanner.nextLine().trim().toLowerCase(Locale.ENGLISH);
-
- for (String mark : SIDEBOARD_MARKS) {
- if (line.startsWith(mark)) {
- return true;
- }
- }
- }
- } catch (Exception e) {
- // ignore error, deckimporter will process it
- }
-
- // not found
- return false;
- }
-
- public static DeckImporter getDeckImporter(String file) {
- if (file == null) {
- return null;
- } if (file.toLowerCase(Locale.ENGLISH).endsWith("dec")) {
- return new DecDeckImporter();
- } else if (file.toLowerCase(Locale.ENGLISH).endsWith("mwdeck")) {
- return new MWSDeckImporter();
- } else if (file.toLowerCase(Locale.ENGLISH).endsWith("txt")) {
- return new TxtDeckImporter(haveSideboardSection(file));
- } else if (file.toLowerCase(Locale.ENGLISH).endsWith("dck")) {
- return new DckDeckImporter();
- } else if (file.toLowerCase(Locale.ENGLISH).endsWith("dek")) {
- return new DekDeckImporter();
- } else {
- return null;
- }
- }
-
- public static DeckCardLists importDeck(String file, StringBuilder errorMessages) {
- DeckImporter deckImporter = getDeckImporter(file);
- if (deckImporter != null) {
- return deckImporter.importDeck(file, errorMessages);
- } else {
- return new DeckCardLists();
- }
- }
-
- public static DeckCardLists importDeck(String file) {
- return importDeck(file, null);
- }
-}
diff --git a/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java
index 7e6efc577a6..2672ff9d3ef 100644
--- a/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java
+++ b/Mage/src/main/java/mage/cards/decks/importer/DekDeckImporter.java
@@ -8,7 +8,7 @@ import mage.cards.repository.CardRepository;
/**
* Created by royk on 11-Sep-16.
*/
-public class DekDeckImporter extends DeckImporter {
+public class DekDeckImporter extends PlainTextDeckImporter {
@Override
protected void readLine(String line, DeckCardLists deckList) {
diff --git a/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java
index bb5c0662186..fd541aa1a51 100644
--- a/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java
+++ b/Mage/src/main/java/mage/cards/decks/importer/MWSDeckImporter.java
@@ -14,7 +14,7 @@ import mage.util.RandomUtil;
*
* @author BetaSteward_at_googlemail.com
*/
-public class MWSDeckImporter extends DeckImporter {
+public class MWSDeckImporter extends PlainTextDeckImporter {
@Override
protected void readLine(String line, DeckCardLists deckList) {
diff --git a/Mage/src/main/java/mage/cards/decks/importer/PlainTextDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/PlainTextDeckImporter.java
new file mode 100644
index 00000000000..c9d99d3aaee
--- /dev/null
+++ b/Mage/src/main/java/mage/cards/decks/importer/PlainTextDeckImporter.java
@@ -0,0 +1,67 @@
+
+
+package mage.cards.decks.importer;
+
+import java.io.File;
+import java.util.Scanner;
+
+import mage.cards.decks.DeckCardLists;
+
+/**
+ *
+ * @author BetaSteward_at_googlemail.com
+ */
+public abstract class PlainTextDeckImporter extends DeckImporter {
+
+ protected StringBuilder sbMessage = new StringBuilder(); //TODO we should stop using this not garbage collectable StringBuilder. It just bloats
+ protected int lineCount;
+
+
+ /**
+ *
+ * @param file file to import
+ * @param errorMessages you can setup output messages to showup to user (set null for fatal exception on messages.count > 0)
+ * @return decks list
+ */
+ public DeckCardLists importDeck(String file, StringBuilder errorMessages) {
+ File f = new File(file);
+ DeckCardLists deckList = new DeckCardLists();
+ if (!f.exists()) {
+ logger.warn("Deckfile " + file + " not found.");
+ return deckList;
+ }
+ lineCount = 0;
+
+ sbMessage.setLength(0);
+ try {
+ try (Scanner scanner = new Scanner(f)) {
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine().trim();
+ lineCount++;
+ readLine(line, deckList);
+ }
+
+ if (sbMessage.length() > 0) {
+ if(errorMessages != null) {
+ // normal output for user
+ errorMessages.append(sbMessage);
+ }else{
+ // fatal error
+ logger.fatal(sbMessage);
+ }
+ }
+ } catch (Exception ex) {
+ logger.fatal(null, ex);
+ }
+ } catch (Exception ex) {
+ logger.fatal(null, ex);
+ }
+ return deckList;
+ }
+
+ public DeckCardLists importDeck(String file) {
+ return importDeck(file, null);
+ }
+
+ protected abstract void readLine(String line, DeckCardLists deckList);
+}
diff --git a/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java b/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java
index 4d593610ff5..a2b5706eb8b 100644
--- a/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java
+++ b/Mage/src/main/java/mage/cards/decks/importer/TxtDeckImporter.java
@@ -14,7 +14,7 @@ import mage.cards.repository.CardRepository;
*
* @author BetaSteward_at_googlemail.com
*/
-public class TxtDeckImporter extends DeckImporter {
+public class TxtDeckImporter extends PlainTextDeckImporter {
private static final String[] SET_VALUES = new String[]{"lands", "creatures", "planeswalkers", "other spells", "sideboard cards",
"Instant", "Land", "Enchantment", "Artifact", "Sorcery", "Planeswalker", "Creature"};