From 78e369043f95e78b27c265f7eab4d766e54054f4 Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Fri, 12 Aug 2016 22:27:26 +0200 Subject: Refactored a lot of things, started adding the rest of the filtering --- src/eu/equalparts/cardbase/card/Card.java | 1 - src/eu/equalparts/cardbase/card/FullCardSet.java | 1 - .../cardbase/cardfield/IntegerCardField.java | 9 +++ .../cardbase/filtering/CardFiltering.java | 2 +- src/eu/equalparts/cardbase/gui/CardView.java | 29 ------- src/eu/equalparts/cardbase/gui/CardbaseGUI.java | 79 ------------------- src/eu/equalparts/cardbase/gui/CardbaseViewer.java | 11 --- .../equalparts/cardbase/json/CardDeserializer.java | 1 - .../equalparts/cardbase/json/CardSerializer.java | 6 -- .../cardbase/json/FullCardSetDeserializer.java | 91 ++++++++++++++++++++++ src/eu/equalparts/cardbase/json/JSON.java | 2 + src/eu/equalparts/cardbase/utils/InputSanity.java | 27 +++++++ src/eu/equalparts/cardbase/utils/MTGUniverse.java | 87 ++++----------------- .../cardbase/filtering/CardFilteringTest.java | 30 +++++-- .../cardbase/sorting/CardSortingTest.java | 20 ----- 15 files changed, 170 insertions(+), 226 deletions(-) delete mode 100644 src/eu/equalparts/cardbase/gui/CardView.java delete mode 100644 src/eu/equalparts/cardbase/gui/CardbaseGUI.java delete mode 100644 src/eu/equalparts/cardbase/gui/CardbaseViewer.java create mode 100644 src/eu/equalparts/cardbase/json/FullCardSetDeserializer.java create mode 100644 src/eu/equalparts/cardbase/utils/InputSanity.java diff --git a/src/eu/equalparts/cardbase/card/Card.java b/src/eu/equalparts/cardbase/card/Card.java index adac286..11cfb77 100644 --- a/src/eu/equalparts/cardbase/card/Card.java +++ b/src/eu/equalparts/cardbase/card/Card.java @@ -29,7 +29,6 @@ public class Card { // Not part of upstream JSON public StringCardField setCode; - public StringCardField imageCode; public static int makeHash(String setCode, String number) { final int prime = 31; diff --git a/src/eu/equalparts/cardbase/card/FullCardSet.java b/src/eu/equalparts/cardbase/card/FullCardSet.java index 72f1e4a..b7db0a5 100644 --- a/src/eu/equalparts/cardbase/card/FullCardSet.java +++ b/src/eu/equalparts/cardbase/card/FullCardSet.java @@ -11,7 +11,6 @@ public class FullCardSet { public String border; public String type; public String block; - public String gathererCode; public Map cards; /** diff --git a/src/eu/equalparts/cardbase/cardfield/IntegerCardField.java b/src/eu/equalparts/cardbase/cardfield/IntegerCardField.java index 4016252..3ee10e7 100644 --- a/src/eu/equalparts/cardbase/cardfield/IntegerCardField.java +++ b/src/eu/equalparts/cardbase/cardfield/IntegerCardField.java @@ -1,5 +1,6 @@ package eu.equalparts.cardbase.cardfield; import eu.equalparts.cardbase.filtering.CardFiltering.Filter; +import eu.equalparts.cardbase.utils.InputSanity; public class IntegerCardField extends CardField { @@ -16,6 +17,14 @@ public class IntegerCardField extends CardField { return get().toString().equalsIgnoreCase(s); case REGEX: return get().toString().matches(s); + case GREATER_THAN: + if (InputSanity.isInteger(s)) { + return get() > Integer.valueOf(s); + } + case SMALLER_THAN: + if (InputSanity.isInteger(s)) { + return get() < Integer.valueOf(s); + } default: return false; } diff --git a/src/eu/equalparts/cardbase/filtering/CardFiltering.java b/src/eu/equalparts/cardbase/filtering/CardFiltering.java index de71f1c..081951f 100644 --- a/src/eu/equalparts/cardbase/filtering/CardFiltering.java +++ b/src/eu/equalparts/cardbase/filtering/CardFiltering.java @@ -16,7 +16,7 @@ import eu.equalparts.cardbase.cardfield.CardField; public class CardFiltering { public enum Filter { - EQUALS, CONTAINS, REGEX; + EQUALS, CONTAINS, REGEX, GREATER_THAN, SMALLER_THAN; } public static void filterByField(List cards, String fieldName, Filter filterType, String filterValue) throws NoSuchFieldException { diff --git a/src/eu/equalparts/cardbase/gui/CardView.java b/src/eu/equalparts/cardbase/gui/CardView.java deleted file mode 100644 index 9774537..0000000 --- a/src/eu/equalparts/cardbase/gui/CardView.java +++ /dev/null @@ -1,29 +0,0 @@ -package eu.equalparts.cardbase.gui; - -import eu.equalparts.cardbase.card.Card; -import javafx.event.EventHandler; -import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; - -public class CardView extends ImageView { - - private static final String BASE_IMG_URL = "http://magiccards.info/scans/en/"; - - public CardView(Card card) { - super(makeUrl(card)); - - addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler() { - - @Override - public void handle(MouseEvent event) { - setVisible(false); - } - }); - - } - - public static String makeUrl(Card card) { - return BASE_IMG_URL + card.imageCode + "/" + card.number + ".jpg"; - } - -} diff --git a/src/eu/equalparts/cardbase/gui/CardbaseGUI.java b/src/eu/equalparts/cardbase/gui/CardbaseGUI.java deleted file mode 100644 index bbbb97c..0000000 --- a/src/eu/equalparts/cardbase/gui/CardbaseGUI.java +++ /dev/null @@ -1,79 +0,0 @@ -package eu.equalparts.cardbase.gui; - -import java.awt.Button; -import java.awt.Frame; -import java.awt.Panel; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; - - -@SuppressWarnings("serial") -public class CardbaseGUI extends Panel { - - /** - * Run the GUI. - * - * @param args arguments passed down to {@code Application.launch()}. - */ - public static void main(String... args) { - Frame f = new Frame("Test"); - - CardbaseGUI c = new CardbaseGUI(); - - f.add(c); - f.pack(); - - f.addWindowListener(new WindowListener() { - @Override - public void windowOpened(WindowEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void windowIconified(WindowEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void windowDeiconified(WindowEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void windowDeactivated(WindowEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void windowClosing(WindowEvent e) { - System.exit(0); - } - - @Override - public void windowClosed(WindowEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void windowActivated(WindowEvent e) { - // TODO Auto-generated method stub - - } - }); - - f.setVisible(true); - } - - - public void init() { - add(new Button("one")); - add(new Button("two")); - } - - -} diff --git a/src/eu/equalparts/cardbase/gui/CardbaseViewer.java b/src/eu/equalparts/cardbase/gui/CardbaseViewer.java deleted file mode 100644 index 30b32fb..0000000 --- a/src/eu/equalparts/cardbase/gui/CardbaseViewer.java +++ /dev/null @@ -1,11 +0,0 @@ -package eu.equalparts.cardbase.gui; - -import javafx.scene.Parent; - -public class CardbaseViewer extends Parent { - - - - - -} diff --git a/src/eu/equalparts/cardbase/json/CardDeserializer.java b/src/eu/equalparts/cardbase/json/CardDeserializer.java index c7ca0a1..7193c53 100644 --- a/src/eu/equalparts/cardbase/json/CardDeserializer.java +++ b/src/eu/equalparts/cardbase/json/CardDeserializer.java @@ -52,7 +52,6 @@ public class CardDeserializer extends StdDeserializer { newCard.imageName = new StringCardField("imageName", node.hasNonNull("imageName") ? node.get("imageName").asText() : null); newCard.watermark = new StringCardField("watermark", node.hasNonNull("watermark") ? node.get("watermark").asText() : null); newCard.setCode = new StringCardField("setCode", node.hasNonNull("setCode") ? node.get("setCode").asText() : null); - newCard.imageCode = new StringCardField("imageCode", node.hasNonNull("imageCode") ? node.get("imageCode").asText() : null); return newCard; } diff --git a/src/eu/equalparts/cardbase/json/CardSerializer.java b/src/eu/equalparts/cardbase/json/CardSerializer.java index 05b41c0..5699061 100644 --- a/src/eu/equalparts/cardbase/json/CardSerializer.java +++ b/src/eu/equalparts/cardbase/json/CardSerializer.java @@ -115,12 +115,6 @@ public class CardSerializer extends JsonSerializer { jGen.writeNullField("setCode"); } - if (card.imageCode.get() != null) { - jGen.writeStringField("imageCode", card.imageCode.get()); - } else { - jGen.writeNullField("imageCode"); - } - jGen.writeEndObject(); } } diff --git a/src/eu/equalparts/cardbase/json/FullCardSetDeserializer.java b/src/eu/equalparts/cardbase/json/FullCardSetDeserializer.java new file mode 100644 index 0000000..73034a0 --- /dev/null +++ b/src/eu/equalparts/cardbase/json/FullCardSetDeserializer.java @@ -0,0 +1,91 @@ +package eu.equalparts.cardbase.json; + + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +import eu.equalparts.cardbase.card.Card; +import eu.equalparts.cardbase.card.FullCardSet; + +public class FullCardSetDeserializer extends StdDeserializer { + + /** + * + */ + private static final long serialVersionUID = 1894617997342518472L; + + protected FullCardSetDeserializer(Class vc) { + super(vc); + } + + public FullCardSetDeserializer() { + this(null); + } + + @Override + public FullCardSet deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + JsonNode jsonTree = jp.getCodec().readTree(jp); + + FullCardSet fcs = new FullCardSet(); + + /* + * These fields are critical, if any of them is not present an exception is thrown. + */ + if (jsonTree.hasNonNull("name")) { + fcs.name = jsonTree.get("name").asText(); + } else { + throw new JsonMappingException("Field \"name\" not found."); + } + + String setCode; + if (jsonTree.hasNonNull("code")) { + setCode = jsonTree.get("code").asText(); + fcs.code = setCode; + } else { + throw new JsonMappingException("Field \"code\" not found."); + } + + if (jsonTree.hasNonNull("releaseDate")) { + fcs.releaseDate = jsonTree.get("releaseDate").asText(); + } else { + throw new JsonMappingException("Field \"releaseDate\" not found."); + } + + if (jsonTree.hasNonNull("cards")) { + // attempt to read card list as a POJO using the standard mapper + 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.set(setCode); + cardMap.put(card.number.get(), card); + } + fcs.cards = cardMap; + } else { + throw new JsonMappingException("Field \"cards\" not found."); + } + + /* + * These fields are optional and are set to null if not present. + */ + fcs.border = jsonTree.hasNonNull("border") ? jsonTree.get("border").asText() : null; + fcs.type = jsonTree.hasNonNull("type") ? jsonTree.get("type").asText() : null; + fcs.block = jsonTree.hasNonNull("block") ? jsonTree.get("block").asText() : null; + fcs.magicCardsInfoCode = jsonTree.hasNonNull("magicCardsInfoCode") ? jsonTree.get("magicCardsInfoCode").asText() : null; + + return fcs; + } + +} diff --git a/src/eu/equalparts/cardbase/json/JSON.java b/src/eu/equalparts/cardbase/json/JSON.java index b06f205..8204be6 100644 --- a/src/eu/equalparts/cardbase/json/JSON.java +++ b/src/eu/equalparts/cardbase/json/JSON.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import eu.equalparts.cardbase.card.Card; +import eu.equalparts.cardbase.card.FullCardSet; /** * This class simply holds an {@code ObjectMapper} to be used whenever JSON must be parsed. @@ -43,6 +44,7 @@ public final class JSON { SimpleModule sm = new SimpleModule(); sm.addDeserializer(Card.class, new CardDeserializer()); sm.addSerializer(Card.class, new CardSerializer()); + sm.addDeserializer(FullCardSet.class, new FullCardSetDeserializer()); objectMapper.registerModule(sm); return objectMapper; diff --git a/src/eu/equalparts/cardbase/utils/InputSanity.java b/src/eu/equalparts/cardbase/utils/InputSanity.java new file mode 100644 index 0000000..0571c73 --- /dev/null +++ b/src/eu/equalparts/cardbase/utils/InputSanity.java @@ -0,0 +1,27 @@ +package eu.equalparts.cardbase.utils; + +public class InputSanity { + public static boolean isInteger(String str) { + if (str == null) { + return false; + } + int length = str.length(); + if (length == 0) { + return false; + } + int i = 0; + if (str.charAt(0) == '-') { + if (length == 1) { + return false; + } + i = 1; + } + for (; i < length; i++) { + char c = str.charAt(i); + if (c < '0' || c > '9') { + return false; + } + } + return true; + } +} diff --git a/src/eu/equalparts/cardbase/utils/MTGUniverse.java b/src/eu/equalparts/cardbase/utils/MTGUniverse.java index 9412e6d..68e41e1 100644 --- a/src/eu/equalparts/cardbase/utils/MTGUniverse.java +++ b/src/eu/equalparts/cardbase/utils/MTGUniverse.java @@ -1,16 +1,16 @@ package eu.equalparts.cardbase.utils; import java.io.IOException; +import java.io.InputStream; import java.net.URL; +import java.net.URLConnection; 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.card.Card; import eu.equalparts.cardbase.card.CardSetInformation; @@ -98,8 +98,8 @@ public final class MTGUniverse { requestedSet = cardSetCache.get(validCode); } // not cached; fetch and cache - else { - requestedSet = parseFullSet(JSON.mapper.readTree(new URL(BASE_DATA_URL + validCode + ".json"))); + else { + requestedSet = JSON.mapper.readValue(getInputStream(BASE_DATA_URL + validCode + ".json"), FullCardSet.class); cardSetCache.put(validCode, requestedSet); } } @@ -113,7 +113,7 @@ public final class MTGUniverse { // if the list isn't cached, fetch and cache it if (cardSets == null) { try { - cardSets = JSON.mapper.readValue(new URL(BASE_DATA_URL + "SetList.json"), new TypeReference>() {}); + cardSets = JSON.mapper.readValue(getInputStream(BASE_DATA_URL + "SetList.json"), new TypeReference>() {}); } catch (Exception e) { System.out.println("Error: could not fetch or parse set code list from upstream, using fallback json..."); // e.printStackTrace(); @@ -152,74 +152,17 @@ public final class MTGUniverse { } /** - * This method is necessary to adapt the list of cards in the json to - * the map format used in cardbase. + * Generates and returns a proper input stream with the correct user agent to ensure + * MTG JSON doesn't return any annoying 403s. * - * @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. + * @param URL + * @return + * @throws IOException */ - private 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.name = jsonTree.get("name").asText(); - } else { - throw new JsonMappingException("Field \"name\" not found."); - } - - String setCode; - if (jsonTree.hasNonNull("code")) { - setCode = jsonTree.get("code").asText(); - fcs.code = setCode; - } else { - throw new JsonMappingException("Field \"code\" not found."); - } - - String imageCode; - if (jsonTree.hasNonNull("magicCardsInfoCode")) { - imageCode = jsonTree.get("magicCardsInfoCode").asText(); - fcs.magicCardsInfoCode = imageCode; - } else { - throw new JsonMappingException("Field \"magicCardsInfoCode\" not found."); - } - - if (jsonTree.hasNonNull("releaseDate")) { - fcs.releaseDate = jsonTree.get("releaseDate").asText(); - } else { - throw new JsonMappingException("Field \"releaseDate\" not found."); - } - - if (jsonTree.hasNonNull("cards")) { - // attempt to read card list as a POJO using the standard mapper - 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.set(setCode); - card.imageCode.set(imageCode); - cardMap.put(card.number.get(), card); - } - fcs.cards = cardMap; - } else { - throw new JsonMappingException("Field \"cards\" not found."); - } - - /* - * These fields are optional and are set to null if not present. - */ - fcs.gathererCode = jsonTree.hasNonNull("gathererCode") ? jsonTree.get("gathererCode").asText() : null; - fcs.border = jsonTree.hasNonNull("border") ? jsonTree.get("border").asText() : null; - fcs.type = jsonTree.hasNonNull("type") ? jsonTree.get("type").asText() : null; - fcs.block = jsonTree.hasNonNull("block") ? jsonTree.get("block").asText() : null; - - return fcs; + private InputStream getInputStream(String url) throws IOException { + URLConnection connection = new URL(url).openConnection(); + connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11"); + connection.connect(); + return connection.getInputStream(); } } \ No newline at end of file diff --git a/test/eu/equalparts/cardbase/filtering/CardFilteringTest.java b/test/eu/equalparts/cardbase/filtering/CardFilteringTest.java index 017e858..8e9d00b 100644 --- a/test/eu/equalparts/cardbase/filtering/CardFilteringTest.java +++ b/test/eu/equalparts/cardbase/filtering/CardFilteringTest.java @@ -74,6 +74,28 @@ public class CardFilteringTest { i++; } } + + @Test + public void filterByNameGreaterThan() throws Exception { + CardFiltering.filterByField(testCards, "name", Filter.GREATER_THAN, "5"); + + assertEquals("Wrong list size.", 8, testCards.size()); + int i = 0; + String[] names = { + "Callow Jushi", + "Coerced Confession", + "Khalni Hydra", + "Nightmare", + "Shivan Dragon", + "Disrupting Shoal", + "Sorin Markov", + "Ugin's Construct", + }; + for (Card card : testCards) { + assertTrue(card.name.get() + " should have been " + names[i] + ", i = " + i, card.name.get().equals(names[i])); + i++; + } + } @Test public void filterByLayoutEquals() throws Exception { @@ -156,7 +178,10 @@ public class CardFilteringTest { @Test public void filterByCMCContains() throws Exception { + CardFiltering.filterByField(testCards, "cmc", Filter.CONTAINS, "5"); + assertEquals("Wrong list size.", 1, testCards.size()); + assertEquals("Coerced Confession", testCards.get(0).name.get()); } @Test @@ -228,9 +253,4 @@ public class CardFilteringTest { public void filterBySetCode() throws Exception { } - - @Test - public void filterByImageCode() throws Exception { - - } } diff --git a/test/eu/equalparts/cardbase/sorting/CardSortingTest.java b/test/eu/equalparts/cardbase/sorting/CardSortingTest.java index 04cf20d..2e4f0e6 100644 --- a/test/eu/equalparts/cardbase/sorting/CardSortingTest.java +++ b/test/eu/equalparts/cardbase/sorting/CardSortingTest.java @@ -350,26 +350,6 @@ public class CardSortingTest { } } - @Test - public void sortByImageCode() throws Exception { - CardSorting.sortByField(testCards, "imageCode"); - int i = 0; - String[] codes = { - "bok", - "bok", - "frf", - "gtc", - "m12", - "m15", - "m15", - "roe", - }; - for (Card card : testCards) { - assertTrue(card.imageCode.get() + " should have been " + codes[i] + ", i = " + i, card.imageCode.get().equals(codes[i])); - i++; - } - } - /* * Edge cases */ -- cgit v1.2.3