From 27be2dd797fc7087c5e362c22c1f30fc377ea0e9 Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Thu, 11 Jun 2015 16:57:42 +0200 Subject: Streamlined Card class, cards are now stored in a hashmap, had to write a method to parse full card set json --- src/eu/equalparts/cardbase/Cardbase.java | 54 +++++++------ src/eu/equalparts/cardbase/data/Card.java | 18 ++--- src/eu/equalparts/cardbase/data/FullCardSet.java | 90 +++++++++++++++++++--- .../cardbase/standalone/CardbaseCLI.java | 11 --- src/eu/equalparts/cardbase/utils/MTGUniverse.java | 80 +++++++++++++++++-- 5 files changed, 190 insertions(+), 63 deletions(-) (limited to 'src/eu/equalparts/cardbase') diff --git a/src/eu/equalparts/cardbase/Cardbase.java b/src/eu/equalparts/cardbase/Cardbase.java index d842031..c5efc85 100644 --- a/src/eu/equalparts/cardbase/Cardbase.java +++ b/src/eu/equalparts/cardbase/Cardbase.java @@ -1,16 +1,16 @@ package eu.equalparts.cardbase; import java.io.File; import java.io.IOException; -import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; -import eu.equalparts.cardbase.comparators.CardComparators; import eu.equalparts.cardbase.data.Card; import eu.equalparts.cardbase.utils.JSON; @@ -22,9 +22,10 @@ import eu.equalparts.cardbase.utils.JSON; public class Cardbase { /** - * The cards in the cardbase. + * The cards in the cardbase, set in key-value pairs where the key is the card hash, + * generated using {makeHash()}. */ - private List cards; + private Map cards; /** * Debug flag is raised when the DEBUG environment variable is set. This causes additional * information to be printed to the console. @@ -35,7 +36,7 @@ public class Cardbase { * Creates an empty cardbase. */ public Cardbase() { - cards = new ArrayList(); + cards = new HashMap(); } /** @@ -48,7 +49,7 @@ public class Cardbase { * @throws IOException if a low-level I/O problem (unexpected end-of-input, network error) occurs. */ public Cardbase(File cardbaseFile) throws JsonParseException, JsonMappingException, IOException { - cards = JSON.mapper.readValue(cardbaseFile, new TypeReference>() {}); + cards = JSON.mapper.readValue(cardbaseFile, new TypeReference>() {}); } /** @@ -79,7 +80,7 @@ public class Cardbase { card.count += count; } else { cardToAdd.count = count; - cards.add(cardToAdd); + cards.put(makeHash(cardToAdd), cardToAdd); } } @@ -104,13 +105,13 @@ public class Cardbase { Integer removed = 0; if (card != null) { if (card.count <= count) { - cards.remove(card); + cards.remove(makeHash(card)); removed = card.count; } else { card.count -= count; removed = count; } - } + } return removed; } @@ -122,32 +123,41 @@ public class Cardbase { * * @return an unmodifiable list of all the cards in the cardbase. */ - public List getCards() { - return Collections.unmodifiableList(cards); + public Collection getCards() { + return Collections.unmodifiableCollection(cards.values()); } - public void sortByName() { - cards.sort(new CardComparators.NameComparator()); - } - /** * Returns a card from the cardbase by set code and number. * If no such card is in the cardbase, returns null. * * @param setCode the set to which the requested card belongs. * @param number the requested card's set number. + * * @return the requested {@code Card} or null if no card is found. */ public Card getCard(String setCode, String number) { - for (Card card : cards) { - if (card.setCode.equals(setCode) && card.number.equals(number)) - return card; - } - - return null; + return cards.get(makeHash(setCode, number)); } + /** + * Generate the hash used as a key in the storage map. + * + * @param setCode the card's set code. + * @param number the card's set number. + * @return the generated hash. + */ private String makeHash(String setCode, String number) { return setCode + number; } + + /** + * Generate the hash used as a key in the storage map. + * + * @param the {@code Card} whose hash is desired. + * @return the generated hash. + */ + private String makeHash(Card card) { + return card.setCode + card.number; + } } diff --git a/src/eu/equalparts/cardbase/data/Card.java b/src/eu/equalparts/cardbase/data/Card.java index 3820223..cca1747 100644 --- a/src/eu/equalparts/cardbase/data/Card.java +++ b/src/eu/equalparts/cardbase/data/Card.java @@ -1,19 +1,12 @@ package eu.equalparts.cardbase.data; -import java.util.List; - public class Card { - public String name = ""; - public String layout = ""; - public List names; - public String manaCost = ""; - public Integer cmc = 0; - public List colors; + public String name; + public String layout; + public String manaCost; + public Integer cmc; public String type; - public List supertypes; - public List types; - public List subtypes; public String rarity; public String text; public String flavor; @@ -23,7 +16,6 @@ public class Card { public String toughness; public Integer loyalty; public Integer multiverseid; - public List variations; public String imageName; public String border; public String watermark; @@ -31,5 +23,5 @@ public class Card { // Not part of upstream JSON public String setCode; public Integer count; - + } \ No newline at end of file diff --git a/src/eu/equalparts/cardbase/data/FullCardSet.java b/src/eu/equalparts/cardbase/data/FullCardSet.java index d469829..e831b74 100644 --- a/src/eu/equalparts/cardbase/data/FullCardSet.java +++ b/src/eu/equalparts/cardbase/data/FullCardSet.java @@ -1,17 +1,19 @@ package eu.equalparts.cardbase.data; -import java.util.List; +import java.util.Collections; +import java.util.Map; public class FullCardSet { private String name; private String code; + private String magicCardsInfoCode; private String releaseDate; private String border; private String type; private String block; private String gathererCode; - private List cards; + private Map cards; /** * @return the set's name. @@ -63,12 +65,12 @@ public class FullCardSet { } /** - * @return a full list of the set's cards. + * @return a full unmodifiable map of the set's cards. */ - public List getCards() { - return cards; + public Map getCards() { + return Collections.unmodifiableMap(cards); } - + /** * Searches for a card by number (the one shown on the card itself). * @@ -76,10 +78,76 @@ public class FullCardSet { * @return the requested {@code Card}, or null if no card is found with that number. */ public Card getCardByNumber(String number) { - for (Card card : cards) { - if (card.number.equals(number)) - return card; - } - return null; + return cards.get(number); + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @param code the code to set + */ + public void setCode(String code) { + this.code = code; + } + + /** + * @param releaseDate the releaseDate to set + */ + public void setReleaseDate(String releaseDate) { + this.releaseDate = releaseDate; + } + + /** + * @param border the border to set + */ + public void setBorder(String border) { + this.border = border; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @param block the block to set + */ + public void setBlock(String block) { + this.block = block; + } + + /** + * @param gathererCode the gathererCode to set + */ + public void setGathererCode(String gathererCode) { + this.gathererCode = gathererCode; + } + + /** + * @param cards the cards to set + */ + public void setCards(Map cards) { + this.cards = cards; + } + + /** + * @return the magicCardsInfoCode + */ + public String getMagicCardsInfoCode() { + return magicCardsInfoCode; + } + + /** + * @param magicCardsInfoCode the magicCardsInfoCode to set + */ + public void setMagicCardsInfoCode(String magicCardsInfoCode) { + this.magicCardsInfoCode = magicCardsInfoCode; } } \ No newline at end of file diff --git a/src/eu/equalparts/cardbase/standalone/CardbaseCLI.java b/src/eu/equalparts/cardbase/standalone/CardbaseCLI.java index f491f6c..be3616a 100644 --- a/src/eu/equalparts/cardbase/standalone/CardbaseCLI.java +++ b/src/eu/equalparts/cardbase/standalone/CardbaseCLI.java @@ -177,8 +177,6 @@ public class CardbaseCLI { } else if (command.equalsIgnoreCase("remove") || command.equalsIgnoreCase("rm")) { remove(args); - } else if (command.equalsIgnoreCase("sort")) { - sort(args); } else { add(command, args); } @@ -410,15 +408,6 @@ public class CardbaseCLI { } } - /** - * Sort the cardbase by a specified parameter. - * - * @param args the ordering to sort by. - */ - public void sort(String[] args) { - cardbase.sortByName(); - } - /** * Add the specified count of the specified card * to the cardbase. diff --git a/src/eu/equalparts/cardbase/utils/MTGUniverse.java b/src/eu/equalparts/cardbase/utils/MTGUniverse.java index 0bcda5c..8c77032 100644 --- a/src/eu/equalparts/cardbase/utils/MTGUniverse.java +++ b/src/eu/equalparts/cardbase/utils/MTGUniverse.java @@ -4,10 +4,13 @@ import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; import eu.equalparts.cardbase.data.Card; import eu.equalparts.cardbase.data.CardSetInformation; @@ -97,11 +100,7 @@ public final class MTGUniverse { } // not cached; fetch, cache and return it else { - requestedSet = JSON.mapper.readValue(new URL(BASE_URL + validCode + ".json"), FullCardSet.class); - // MTG JSON does not include set code in the card information, but it is useful for sorting - for (Card card : requestedSet.getCards()) { - card.setCode = validCode; - } + requestedSet = parseFullSet(JSON.mapper.readValue(new URL(BASE_URL + validCode + ".json"), JsonNode.class)); cardSetCache.put(validCode, requestedSet); } } @@ -152,4 +151,73 @@ public final class MTGUniverse { } return null; } -} + + /** + * This method is necessary to adapt the list of cards in the json to + * the map format used in cardbase. + * + * @param jsonTree the tree-representation of the json to be parsed. + * @return the parsed full card set. + * + * @throws JsonMappingException if the upstream JSON does not map to {@code FullCardSet}. + * @throws IOException if a low-level I/O problem (unexpected end-of-input, network error) occurs. + */ + private static FullCardSet parseFullSet(JsonNode jsonTree) throws JsonMappingException, IOException { + + FullCardSet fcs = new FullCardSet(); + + /* + * These fields are critical, if any of them is not present an exception is thrown. + */ + if (jsonTree.hasNonNull("name")) { + fcs.setName(jsonTree.get("name").asText()); + } else { + throw new JsonMappingException("Field \"name\" not found."); + } + + String setCode; + if (jsonTree.hasNonNull("code")) { + setCode = jsonTree.get("code").asText(); + fcs.setCode(setCode); + } else { + throw new JsonMappingException("Field \"code\" not found."); + } + + if (jsonTree.hasNonNull("releaseDate")) { + fcs.setReleaseDate(jsonTree.get("releaseDate").asText()); + } else { + throw new JsonMappingException("Field \"releaseDate\" not found."); + } + + /* + * These fields are optional and are set to null if not present. + */ + fcs.setGathererCode(jsonTree.hasNonNull("gathererCode") ? jsonTree.get("gathererCode").asText() : null); + fcs.setBorder(jsonTree.hasNonNull("border") ? jsonTree.get("border").asText() : null); + fcs.setType(jsonTree.hasNonNull("type") ? jsonTree.get("type").asText() : null); + fcs.setMagicCardsInfoCode(jsonTree.hasNonNull("magicCardsInfoCode") ? jsonTree.get("magicCardsInfoCode").asText() : null); + fcs.setBlock(jsonTree.hasNonNull("block") ? jsonTree.get("block").asText() : null); + + /* + * This is a critical field which must be present, if not an exception is thrown. + */ + if (jsonTree.hasNonNull("cards")) { + // attempt to card list as POJO + List rawList = jsonTree.get("cards").traverse(JSON.mapper).readValueAs(new TypeReference>() {}); + + // generate the map + Map cardMap = new HashMap(); + for (Card card : rawList) { + // add set code for convenience + card.setCode = setCode; + cardMap.put(card.number, card); + } + fcs.setCards(cardMap); + } else { + throw new JsonMappingException("Field \"cards\" not found."); + } + + return fcs; + + } +} \ No newline at end of file -- cgit v1.2.3