From 53c7f09b54b212fede5f9efbdf09e7a8a0395246 Mon Sep 17 00:00:00 2001 From: iMoHax Date: Fri, 16 Sep 2016 15:14:33 +0300 Subject: [PATCH] implement EDDN parser --- .../main/java/ru/trader/emdn/EMDNParser.java | 250 +++++++++++++++++ .../src/main/java/ru/trader/emdn/Station.java | 37 --- .../java/ru/trader/emdn/entities/Body.java | 46 ++++ .../java/ru/trader/emdn/entities/Header.java | 46 ++++ .../java/ru/trader/emdn/entities/Item.java | 78 ++++++ .../ru/trader/emdn/entities/LEVEL_TYPE.java | 24 ++ .../java/ru/trader/emdn/entities/Message.java | 39 +++ .../ru/trader/emdn/entities/StarSystem.java | 40 +++ .../java/ru/trader/emdn/entities/Station.java | 30 ++ utils/src/test/java/ru/trader/TestUtils.java | 29 ++ .../test/java/ru/trader/emdn/ParserTest.java | 258 ++++++++++++++++++ .../test/resources/emdn/commodity-v.1.json | 117 ++++++++ .../test/resources/emdn/commodity-v.2.json | 119 ++++++++ .../test/resources/emdn/commodity-v.3.json | 114 ++++++++ utils/src/test/resources/emdn/v1.json | 21 ++ utils/src/test/resources/emdn/v1e.json | 13 + utils/src/test/resources/emdn/v1m.json | 18 ++ utils/src/test/resources/emdn/v2.json | 33 +++ utils/src/test/resources/emdn/v2e.json | 13 + utils/src/test/resources/emdn/v2m.json | 22 ++ 20 files changed, 1310 insertions(+), 37 deletions(-) create mode 100644 utils/src/main/java/ru/trader/emdn/EMDNParser.java delete mode 100644 utils/src/main/java/ru/trader/emdn/Station.java create mode 100644 utils/src/main/java/ru/trader/emdn/entities/Body.java create mode 100644 utils/src/main/java/ru/trader/emdn/entities/Header.java create mode 100644 utils/src/main/java/ru/trader/emdn/entities/Item.java create mode 100644 utils/src/main/java/ru/trader/emdn/entities/LEVEL_TYPE.java create mode 100644 utils/src/main/java/ru/trader/emdn/entities/Message.java create mode 100644 utils/src/main/java/ru/trader/emdn/entities/StarSystem.java create mode 100644 utils/src/main/java/ru/trader/emdn/entities/Station.java create mode 100644 utils/src/test/java/ru/trader/TestUtils.java create mode 100644 utils/src/test/java/ru/trader/emdn/ParserTest.java create mode 100644 utils/src/test/resources/emdn/commodity-v.1.json create mode 100644 utils/src/test/resources/emdn/commodity-v.2.json create mode 100644 utils/src/test/resources/emdn/commodity-v.3.json create mode 100644 utils/src/test/resources/emdn/v1.json create mode 100644 utils/src/test/resources/emdn/v1e.json create mode 100644 utils/src/test/resources/emdn/v1m.json create mode 100644 utils/src/test/resources/emdn/v2.json create mode 100644 utils/src/test/resources/emdn/v2e.json create mode 100644 utils/src/test/resources/emdn/v2m.json diff --git a/utils/src/main/java/ru/trader/emdn/EMDNParser.java b/utils/src/main/java/ru/trader/emdn/EMDNParser.java new file mode 100644 index 0000000..c6febba --- /dev/null +++ b/utils/src/main/java/ru/trader/emdn/EMDNParser.java @@ -0,0 +1,250 @@ +package ru.trader.emdn; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.trader.emdn.entities.*; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; + +public class EMDNParser { + private final static Logger LOG = LoggerFactory.getLogger(EMDNParser.class); + + private final ObjectMapper mapper; + private final static ObjectMapper DEFAULT_MAPPER = new ObjectMapper(); + + public EMDNParser() { + this(DEFAULT_MAPPER); + } + + public EMDNParser(ObjectMapper mapper) { + this.mapper = mapper; + } + + @Nullable + public Message parse(String json) throws IOException { + JsonParser parser = mapper.getFactory().createParser(json); + JsonNode node = parser.readValueAsTree(); + String schema = node.get("$schemaRef").asText(); + PARSERS p = PARSERS.getParser(schema); + if (p == null){ + LOG.warn("Unknown EDDN message schema {}", schema); + return null; + } + return p.parse(node); + } + + private enum PARSERS { + V1("http://schemas.elite-markets.net/eddn/commodity/1"){ + @Override + protected Body parseBody(JsonNode node) { + if (node == null){ + LOG.warn("Not found message body on parse EDDN message"); + return null; + } + JsonNode systemName = node.get("systemName"); + JsonNode stationName = node.get("stationName"); + JsonNode timestamp = node.get("timestamp"); + if (systemName == null || stationName == null || timestamp == null){ + LOG.warn("Body EDDN message don't have required fields"); + return null; + } + StarSystem starSystem = new StarSystem(systemName.asText()); + Station station = new Station(stationName.asText()); + LocalDateTime dt = LocalDateTime.parse(timestamp.asText(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + Body body = new Body(starSystem, station); + body.setTimestamp(dt); + body.addAll(parseCommodities(node)); + return body; + } + + @Override + protected Collection parseCommodities(JsonNode node) { + JsonNode name = node.get("itemName"); + JsonNode buyPrice = node.get("buyPrice"); + JsonNode supply = node.get("stationStock"); + JsonNode supplyLevel = node.get("supplyLevel"); + JsonNode sellPrice = node.get("sellPrice"); + JsonNode demand = node.get("demand"); + JsonNode demandLevel = node.get("demandLevel"); + if (name == null || buyPrice == null || supply == null || sellPrice == null || demand == null){ + LOG.warn("Commodity of EDDN message don't have required fields"); + return null; + } + Item item = new Item(name.asText(), buyPrice.asLong(), supply.asLong(), sellPrice.asLong(), demand.asLong()); + if (supplyLevel != null){ + item.setSupplyLevel(LEVEL_TYPE.fromJSON(supplyLevel.asText())); + } + if (demandLevel != null){ + item.setDemandLevel(LEVEL_TYPE.fromJSON(demandLevel.asText())); + } + return Collections.singleton(item); + } + }, + + V2("http://schemas.elite-markets.net/eddn/commodity/2"), + + V3("http://schemas.elite-markets.net/eddn/commodity/3"){ + @Override + protected Body parseBody(JsonNode node) { + if (node == null){ + LOG.warn("Not found message body on parse EDDN message"); + return null; + } + JsonNode systemNode = node.get("system"); + JsonNode stationNode = node.get("station"); + JsonNode timestamp = node.get("timestamp"); + JsonNode commodities = node.get("commodities"); + if (systemNode == null || stationNode == null || timestamp == null || commodities == null){ + LOG.warn("Body EDDN message don't have required fields"); + return null; + } + StarSystem starSystem = parseSystem(systemNode); + Station station = parseStation(stationNode); + LocalDateTime dt = LocalDateTime.parse(timestamp.asText(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + Body body = new Body(starSystem, station); + body.setTimestamp(dt); + body.addAll(parseCommodities(commodities)); + return body; + } + + private Station parseStation(JsonNode node) { + JsonNode name = node.get("name"); + JsonNode id = node.get("id"); + if (name == null){ + LOG.warn("Station in EDDN message don't have required fields"); + return null; + } + Station station = new Station(name.asText()); + if (id != null){ + station.setId(id.asLong()); + } + return station; + } + + private StarSystem parseSystem(JsonNode node) { + JsonNode name = node.get("name"); + JsonNode id = node.get("id"); + JsonNode address = node.get("address"); + if (name == null){ + LOG.warn("System in EDDN message don't have required fields"); + return null; + } + StarSystem system = new StarSystem(name.asText()); + if (id != null){ + system.setId(id.asLong()); + } + if (address != null){ + system.setAddress(address.asLong()); + } + return system; + } + + + }; + + private final String schema; + + public Message parse(JsonNode node){ + Header header = parseHeader(node.get("header")); + Body body = parseBody(node.get("message")); + if (header == null || body == null) return null; + return new Message(schema, header, body); + } + + protected Header parseHeader(JsonNode node){ + if (node == null){ + LOG.warn("Not found header on parse EDDN message"); + return null; + } + JsonNode uploaderID = node.get("uploaderID"); + JsonNode softwareName = node.get("softwareName"); + JsonNode softwareVersion = node.get("softwareVersion"); + JsonNode gatewayTimestamp = node.get("gatewayTimestamp"); + if (uploaderID == null || softwareName == null || softwareVersion == null){ + LOG.warn("Header EDDN message don't have required fields"); + return null; + } + Header header = new Header(uploaderID.asText(), softwareName.asText(), softwareVersion.asText()); + if (gatewayTimestamp != null){ + LocalDateTime dt = LocalDateTime.parse(gatewayTimestamp.asText(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + header.setGatewayTimestamp(dt); + } + return header; + } + + protected Body parseBody(JsonNode node){ + if (node == null){ + LOG.warn("Not found message body on parse EDDN message"); + return null; + } + JsonNode systemName = node.get("systemName"); + JsonNode stationName = node.get("stationName"); + JsonNode timestamp = node.get("timestamp"); + JsonNode commodities = node.get("commodities"); + if (systemName == null || stationName == null || timestamp == null || commodities == null){ + LOG.warn("Body EDDN message don't have required fields"); + return null; + } + StarSystem starSystem = new StarSystem(systemName.asText()); + Station station = new Station(stationName.asText()); + LocalDateTime dt = LocalDateTime.parse(timestamp.asText(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + Body body = new Body(starSystem, station); + body.setTimestamp(dt); + body.addAll(parseCommodities(commodities)); + return body; + } + + protected Collection parseCommodities(JsonNode commodities) { + Collection res = new ArrayList<>(); + for (Iterator iterator = commodities.elements(); iterator.hasNext(); ) { + JsonNode node = iterator.next(); + JsonNode name = node.get("name"); + JsonNode id = node.get("id"); + JsonNode buyPrice = node.get("buyPrice"); + JsonNode supply = node.get("supply"); + JsonNode supplyLevel = node.get("supplyLevel"); + JsonNode sellPrice = node.get("sellPrice"); + JsonNode demand = node.get("demand"); + JsonNode demandLevel = node.get("demandLevel"); + if (name == null || buyPrice == null || supply == null || sellPrice == null || demand == null){ + LOG.warn("Commodity of EDDN message don't have required fields"); + return null; + } + Item item = new Item(name.asText(), buyPrice.asLong(), supply.asLong(), sellPrice.asLong(), demand.asLong()); + if (id != null){ + item.setId(id.asLong()); + } + if (supplyLevel != null){ + item.setSupplyLevel(LEVEL_TYPE.fromJSON(supplyLevel.asText())); + } + if (demandLevel != null){ + item.setDemandLevel(LEVEL_TYPE.fromJSON(demandLevel.asText())); + } + res.add(item); + } + return res; + } + + private PARSERS(String schema) { + this.schema = schema; + } + + public static PARSERS getParser(String schema){ + for (PARSERS parser : PARSERS.values()) { + if (parser.schema.equals(schema)) return parser; + } + return null; + } + } + +} diff --git a/utils/src/main/java/ru/trader/emdn/Station.java b/utils/src/main/java/ru/trader/emdn/Station.java deleted file mode 100644 index ab6d369..0000000 --- a/utils/src/main/java/ru/trader/emdn/Station.java +++ /dev/null @@ -1,37 +0,0 @@ -package ru.trader.emdn; - -import java.util.concurrent.ConcurrentHashMap; - -public class Station { - private final String name; - private final ConcurrentHashMap items = new ConcurrentHashMap<>(15, 0.9f, 1); - - public Station(String name) { - this.name = name; - } - - public ItemData getData(String name){ - return items.get(name); - } - - void update(ItemData item){ - items.put(item.getName(), item); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Station)) return false; - Station station = (Station) o; - return name.equals(station.name); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - public String getName() { - return name; - } -} diff --git a/utils/src/main/java/ru/trader/emdn/entities/Body.java b/utils/src/main/java/ru/trader/emdn/entities/Body.java new file mode 100644 index 0000000..5a9572e --- /dev/null +++ b/utils/src/main/java/ru/trader/emdn/entities/Body.java @@ -0,0 +1,46 @@ +package ru.trader.emdn.entities; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collection; + +public class Body { + private final StarSystem system; + private final Station station; + private LocalDateTime timestamp; + private final Collection commodities; + + public Body(StarSystem system, Station station) { + this.system = system; + this.station = station; + commodities = new ArrayList<>(); + } + + public StarSystem getSystem() { + return system; + } + + public Station getStation() { + return station; + } + + public LocalDateTime getTimestamp() { + return timestamp; + } + + public void setTimestamp(LocalDateTime timestamp) { + this.timestamp = timestamp; + } + + public Collection getCommodities() { + return commodities; + } + + public void add(Item item){ + commodities.add(item); + } + + public void addAll(Collection items){ + commodities.addAll(items); + } +} diff --git a/utils/src/main/java/ru/trader/emdn/entities/Header.java b/utils/src/main/java/ru/trader/emdn/entities/Header.java new file mode 100644 index 0000000..c024361 --- /dev/null +++ b/utils/src/main/java/ru/trader/emdn/entities/Header.java @@ -0,0 +1,46 @@ +package ru.trader.emdn.entities; + +import java.time.LocalDateTime; + +public class Header { + private final String uploaderId; + private final String softwareName; + private final String softwareVersion; + private LocalDateTime gatewayTimestamp; + + public Header(String uploaderId, String softwareName, String softwareVersion) { + this.uploaderId = uploaderId; + this.softwareName = softwareName; + this.softwareVersion = softwareVersion; + } + + public String getUploaderId() { + return uploaderId; + } + + public String getSoftwareName() { + return softwareName; + } + + public String getSoftwareVersion() { + return softwareVersion; + } + + public LocalDateTime getGatewayTimestamp() { + return gatewayTimestamp; + } + + public void setGatewayTimestamp(LocalDateTime gatewayTimestamp) { + this.gatewayTimestamp = gatewayTimestamp; + } + + @Override + public String toString() { + return "Header{" + + "uploaderId='" + uploaderId + '\'' + + ", softwareName='" + softwareName + '\'' + + ", softwareVersion='" + softwareVersion + '\'' + + ", gatewayTimestamp=" + gatewayTimestamp + + "} " + super.toString(); + } +} diff --git a/utils/src/main/java/ru/trader/emdn/entities/Item.java b/utils/src/main/java/ru/trader/emdn/entities/Item.java new file mode 100644 index 0000000..9b4777e --- /dev/null +++ b/utils/src/main/java/ru/trader/emdn/entities/Item.java @@ -0,0 +1,78 @@ +package ru.trader.emdn.entities; + +public class Item { + private final String name; + private Long id; + private final long buyPrice; + private final long supply; + private LEVEL_TYPE supplyLevel; + private final long sellPrice; + private final long demand; + private LEVEL_TYPE demandLevel; + + public Item(String name, long buyPrice, long supply, long sellPrice, long demand) { + this.name = name; + this.buyPrice = buyPrice; + this.supply = supply; + this.sellPrice = sellPrice; + this.demand = demand; + } + + public String getName() { + return name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public long getBuyPrice() { + return buyPrice; + } + + public long getSupply() { + return supply; + } + + public LEVEL_TYPE getSupplyLevel() { + return supplyLevel; + } + + public void setSupplyLevel(LEVEL_TYPE supplyLevel) { + this.supplyLevel = supplyLevel; + } + + public long getSellPrice() { + return sellPrice; + } + + public long getDemand() { + return demand; + } + + public LEVEL_TYPE getDemandLevel() { + return demandLevel; + } + + public void setDemandLevel(LEVEL_TYPE demandLevel) { + this.demandLevel = demandLevel; + } + + @Override + public String toString() { + return "Item{" + + "name='" + name + '\'' + + ", id=" + id + + ", buyPrice=" + buyPrice + + ", supply=" + supply + + ", supplyLevel=" + supplyLevel + + ", sellPrice=" + sellPrice + + ", demand=" + demand + + ", demandLevel=" + demandLevel + + "} " + super.toString(); + } +} diff --git a/utils/src/main/java/ru/trader/emdn/entities/LEVEL_TYPE.java b/utils/src/main/java/ru/trader/emdn/entities/LEVEL_TYPE.java new file mode 100644 index 0000000..2d952ef --- /dev/null +++ b/utils/src/main/java/ru/trader/emdn/entities/LEVEL_TYPE.java @@ -0,0 +1,24 @@ +package ru.trader.emdn.entities; + +public enum LEVEL_TYPE { + LOW("Low"), MEDIUM("Med"), HIGH("High"); + + private final String jsonText; + + private LEVEL_TYPE(String jsonText) { + this.jsonText = jsonText; + } + + public String toJSON(){ + return jsonText; + } + + public static LEVEL_TYPE fromJSON(String text){ + for (LEVEL_TYPE level : LEVEL_TYPE.values()) { + if (level.jsonText.equals(text)) return level; + } + return null; + } + + +} diff --git a/utils/src/main/java/ru/trader/emdn/entities/Message.java b/utils/src/main/java/ru/trader/emdn/entities/Message.java new file mode 100644 index 0000000..1b26454 --- /dev/null +++ b/utils/src/main/java/ru/trader/emdn/entities/Message.java @@ -0,0 +1,39 @@ +package ru.trader.emdn.entities; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Message { + @JsonProperty("$schemaRef") + private String schemaRef; + + private Header header; + + private Body body; + + public Message(String schemaRef, Header header, Body body) { + this.schemaRef = schemaRef; + this.header = header; + this.body = body; + } + + public String getSchemaRef() { + return schemaRef; + } + + public Header getHeader() { + return header; + } + + public Body getBody() { + return body; + } + + @Override + public String toString() { + return "Message{" + + "schemaRef='" + schemaRef + '\'' + + ", header=" + header + + ", body=" + body + + "} " + super.toString(); + } +} diff --git a/utils/src/main/java/ru/trader/emdn/entities/StarSystem.java b/utils/src/main/java/ru/trader/emdn/entities/StarSystem.java new file mode 100644 index 0000000..3de7a12 --- /dev/null +++ b/utils/src/main/java/ru/trader/emdn/entities/StarSystem.java @@ -0,0 +1,40 @@ +package ru.trader.emdn.entities; + +public class StarSystem { + private final String name; + private Long id; + private Long address; + + public StarSystem(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getAddress() { + return address; + } + + public void setAddress(Long address) { + this.address = address; + } + + @Override + public String toString() { + return "StarSystem{" + + "name='" + name + '\'' + + ", id=" + id + + ", address=" + address + + "} " + super.toString(); + } +} diff --git a/utils/src/main/java/ru/trader/emdn/entities/Station.java b/utils/src/main/java/ru/trader/emdn/entities/Station.java new file mode 100644 index 0000000..e0666a8 --- /dev/null +++ b/utils/src/main/java/ru/trader/emdn/entities/Station.java @@ -0,0 +1,30 @@ +package ru.trader.emdn.entities; + +public class Station { + private final String name; + private Long id; + + public Station(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Override + public String toString() { + return "Station{" + + "name='" + name + '\'' + + ", id=" + id + + "} " + super.toString(); + } +} diff --git a/utils/src/test/java/ru/trader/TestUtils.java b/utils/src/test/java/ru/trader/TestUtils.java new file mode 100644 index 0000000..16075c0 --- /dev/null +++ b/utils/src/test/java/ru/trader/TestUtils.java @@ -0,0 +1,29 @@ +package ru.trader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class TestUtils { + private final static Logger LOG = LoggerFactory.getLogger(TestUtils.class); + + public static String read(InputStream is){ + StringBuilder builder = new StringBuilder(); + String line; + try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))){ + while ((line = reader.readLine()) != null){ + if (builder.length() > 0){ + builder.append("\n"); + } + builder.append(line); + } + } catch (IOException e) { + LOG.error("Error on read file", e); + } + return builder.toString(); + } +} diff --git a/utils/src/test/java/ru/trader/emdn/ParserTest.java b/utils/src/test/java/ru/trader/emdn/ParserTest.java new file mode 100644 index 0000000..6125de5 --- /dev/null +++ b/utils/src/test/java/ru/trader/emdn/ParserTest.java @@ -0,0 +1,258 @@ +package ru.trader.emdn; + +import com.fasterxml.jackson.core.JsonParseException; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.trader.TestUtils; +import ru.trader.emdn.entities.*; + +import java.io.InputStream; +import java.time.LocalDateTime; +import java.util.Collection; + +public class ParserTest extends Assert { + private final static Logger LOG = LoggerFactory.getLogger(ParserTest.class); + + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test + public void testParseV1() throws Exception { + EMDNParser parser = new EMDNParser(); + + try (InputStream is = getClass().getResourceAsStream("/emdn/v1.json")) { + String json = TestUtils.read(is); + Message message = parser.parse(json); + assertNotNull(message); + assertEquals("http://schemas.elite-markets.net/eddn/commodity/1", message.getSchemaRef()); + Header header = message.getHeader(); + assertNotNull(header); + assertEquals("abcdef0123456789", header.getUploaderId()); + assertEquals("My Awesome Market Uploader", header.getSoftwareName()); + assertEquals("v3.14", header.getSoftwareVersion()); + assertEquals(LocalDateTime.of(2014, 11, 17, 13, 35), header.getGatewayTimestamp()); + Body body = message.getBody(); + assertNotNull(body); + assertEquals(LocalDateTime.of(2014, 11, 17, 12, 34, 56), body.getTimestamp()); + StarSystem system = body.getSystem(); + assertNotNull(system); + assertEquals("Eranin", system.getName()); + assertNull(system.getId()); + assertNull(system.getAddress()); + Station station = body.getStation(); + assertNotNull(station); + assertEquals("Azeban Orbital", station.getName()); + assertNull(station.getId()); + Collection items = body.getCommodities(); + assertNotNull(items); + assertEquals(1, items.size()); + Item item = items.iterator().next(); + assertNotNull(item); + assertEquals("Gold", item.getName()); + assertNull(item.getId()); + assertEquals(1024, item.getBuyPrice()); + assertEquals(7, item.getSupply()); + assertEquals(LEVEL_TYPE.LOW, item.getSupplyLevel()); + assertEquals(1138, item.getSellPrice()); + assertEquals(42, item.getDemand()); + assertEquals(LEVEL_TYPE.MEDIUM, item.getDemandLevel()); + } + } + + + @Test + public void testParseV2() throws Exception { + EMDNParser parser = new EMDNParser(); + + try (InputStream is = getClass().getResourceAsStream("/emdn/v2.json")) { + String json = TestUtils.read(is); + Message message = parser.parse(json); + assertNotNull(message); + assertEquals("http://schemas.elite-markets.net/eddn/commodity/2", message.getSchemaRef()); + Header header = message.getHeader(); + assertNotNull(header); + assertEquals("abcdef0123456789", header.getUploaderId()); + assertEquals("My Awesome Market Uploader", header.getSoftwareName()); + assertEquals("v3.14", header.getSoftwareVersion()); + assertEquals(LocalDateTime.of(2014, 11, 17, 13, 35), header.getGatewayTimestamp()); + Body body = message.getBody(); + assertNotNull(body); + assertEquals(LocalDateTime.of(2014, 11, 17, 12, 34, 56), body.getTimestamp()); + StarSystem system = body.getSystem(); + assertNotNull(system); + assertEquals("Eranin", system.getName()); + assertNull(system.getId()); + assertNull(system.getAddress()); + Station station = body.getStation(); + assertNotNull(station); + assertEquals("Azeban Orbital", station.getName()); + assertNull(station.getId()); + Collection items = body.getCommodities(); + assertNotNull(items); + assertEquals(2, items.size()); + int found = 0; + for (Item item : items) { + assertNotNull(item); + if ("Gold".equals(item.getName())){ + found++; + assertNull(item.getId()); + assertEquals(1024, item.getBuyPrice()); + assertEquals(7, item.getSupply()); + assertEquals(LEVEL_TYPE.LOW, item.getSupplyLevel()); + assertEquals(1138, item.getSellPrice()); + assertEquals(42, item.getDemand()); + assertEquals(LEVEL_TYPE.MEDIUM, item.getDemandLevel()); + } else + if ("Explosives".equals(item.getName())){ + found++; + assertNull(item.getId()); + assertEquals(999, item.getBuyPrice()); + assertEquals(1500, item.getSupply()); + assertEquals(LEVEL_TYPE.LOW, item.getSupplyLevel()); + assertEquals(0, item.getSellPrice()); + assertEquals(0, item.getDemand()); + assertNull(item.getDemandLevel()); + } + } + assertEquals("Expected items not found", 2, found); + } + } + + @Test + public void testParseV1Min() throws Exception { + EMDNParser parser = new EMDNParser(); + + try (InputStream is = getClass().getResourceAsStream("/emdn/v1m.json")) { + String json = TestUtils.read(is); + Message message = parser.parse(json); + assertNotNull(message); + assertEquals("http://schemas.elite-markets.net/eddn/commodity/1", message.getSchemaRef()); + Header header = message.getHeader(); + assertNotNull(header); + assertEquals("abcdef0123456789", header.getUploaderId()); + assertEquals("My Awesome Market Uploader", header.getSoftwareName()); + assertEquals("v3.14", header.getSoftwareVersion()); + assertNull(header.getGatewayTimestamp()); + Body body = message.getBody(); + assertNotNull(body); + assertEquals(LocalDateTime.of(2014, 11, 17, 12, 34, 56), body.getTimestamp()); + StarSystem system = body.getSystem(); + assertNotNull(system); + assertEquals("Eranin", system.getName()); + assertNull(system.getId()); + assertNull(system.getAddress()); + Station station = body.getStation(); + assertNotNull(station); + assertEquals("Azeban Orbital", station.getName()); + assertNull(station.getId()); + Collection items = body.getCommodities(); + assertNotNull(items); + assertEquals(1, items.size()); + Item item = items.iterator().next(); + assertNotNull(item); + assertEquals("Gold", item.getName()); + assertNull(item.getId()); + assertEquals(1024, item.getBuyPrice()); + assertEquals(7, item.getSupply()); + assertNull(item.getSupplyLevel()); + assertEquals(1138, item.getSellPrice()); + assertEquals(42, item.getDemand()); + assertNull(item.getDemandLevel()); + } + } + + + @Test + public void testParseV2Min() throws Exception { + EMDNParser parser = new EMDNParser(); + + try (InputStream is = getClass().getResourceAsStream("/emdn/v2m.json")) { + String json = TestUtils.read(is); + Message message = parser.parse(json); + assertNotNull(message); + assertEquals("http://schemas.elite-markets.net/eddn/commodity/2", message.getSchemaRef()); + Header header = message.getHeader(); + assertNotNull(header); + assertEquals("abcdef0123456789", header.getUploaderId()); + assertEquals("My Awesome Market Uploader", header.getSoftwareName()); + assertEquals("v3.14", header.getSoftwareVersion()); + assertNull(header.getGatewayTimestamp()); + Body body = message.getBody(); + assertNotNull(body); + assertEquals(LocalDateTime.of(2014, 11, 17, 12, 34, 56), body.getTimestamp()); + StarSystem system = body.getSystem(); + assertNotNull(system); + assertEquals("Eranin", system.getName()); + assertNull(system.getId()); + assertNull(system.getAddress()); + Station station = body.getStation(); + assertNotNull(station); + assertEquals("Azeban Orbital", station.getName()); + assertNull(station.getId()); + Collection items = body.getCommodities(); + assertNotNull(items); + assertEquals(1, items.size()); + for (Item item : items) { + assertNotNull(item); + assertEquals("Gold", item.getName()); + assertNull(item.getId()); + assertEquals(1024, item.getBuyPrice()); + assertEquals(7, item.getSupply()); + assertNull(item.getSupplyLevel()); + assertEquals(1138, item.getSellPrice()); + assertEquals(42, item.getDemand()); + assertNull(item.getDemandLevel()); + } + } + } + + @Test + public void testParseV1Error() throws Exception { + EMDNParser parser = new EMDNParser(); + try (InputStream is = getClass().getResourceAsStream("/emdn/v1e.json")) { + String json = TestUtils.read(is); + Message message = parser.parse(json); + assertNull(message); + } + } + + @Test + public void testParseV2Error() throws Exception { + EMDNParser parser = new EMDNParser(); + try (InputStream is = getClass().getResourceAsStream("/emdn/v2e.json")) { + String json = TestUtils.read(is); + Message message = parser.parse(json); + assertNull(message); + } + } + + @Test + public void testParseError() throws Exception { + EMDNParser parser = new EMDNParser(); + String json = "Eranin sdfe adsf"; + + exception.expect(JsonParseException.class); + parser.parse(json); + } + + @Test + public void testParseError2() throws Exception { + EMDNParser parser = new EMDNParser(); + + + String json = "{\n" + + " \"$schemaRef\": \"http://schemas.elite-markets.net/eddn/commodity/2\",\n" + + " \"header\": {\n" + + " \"uploaderID\": \"abcdef0123456789\",\n" + + " \"softwareName\": \"My Aweso"; + + exception.expect(JsonParseException.class); + parser.parse(json); + + } + +} diff --git a/utils/src/test/resources/emdn/commodity-v.1.json b/utils/src/test/resources/emdn/commodity-v.1.json new file mode 100644 index 0000000..8575f6f --- /dev/null +++ b/utils/src/test/resources/emdn/commodity-v.1.json @@ -0,0 +1,117 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "http://schemas.elite-markets.net/eddn/commodity/1#", + "type": "object", + "additionalProperties": false, + "properties": { + "$schemaRef": { + "id": "#$schemaRef", + "type": "string", + "additionalProperties": false + }, + "header": { + "id": "#header", + "type": "object", + "additionalProperties": true, + "properties": { + "uploaderID": { + "id": "#uploaderID", + "type": "string", + "additionalProperties": false + }, + "softwareName": { + "id": "#softwareName", + "type": "string", + "additionalProperties": false + }, + "softwareVersion": { + "id": "#softwareVersion", + "type": "string", + "additionalProperties": false + }, + "gatewayTimestamp": { + "id": "#gatewayTimestamp", + "type": "string", + "format": "date-time", + "description": "Timestamp upon receipt at the gateway. If present, this property will be overwritten by the gateway; submitters are not intended to populate this property.", + "additionalProperties": false + } + } + }, + "message": { + "id": "#message", + "type": "object", + "additionalProperties": true, + "properties": { + "systemName": { + "id": "#systemName", + "type": "string", + "additionalProperties": false + }, + "stationName": { + "id": "#stationName", + "type": "string", + "additionalProperties": false + }, + "itemName": { + "id": "#itemName", + "type": "string", + "additionalProperties": false + }, + "buyPrice": { + "id": "#buyPrice", + "type": "integer", + "description": "Price to buy from the market", + "additionalProperties": false + }, + "stationStock": { + "id": "#stationStock", + "type": "integer", + "additionalProperties": false + }, + "supplyLevel": { + "$ref": "#/definitions/levelType" + }, + "sellPrice": { + "id": "#sellPrice", + "type": "integer", + "description": "Price to sell to the market", + "additionalProperties": false + }, + "demand": { + "id": "#demand", + "type": "integer", + "additionalProperties": false + }, + "demandLevel": { + "$ref": "#/definitions/levelType" + }, + "timestamp": { + "id": "#timestamp", + "type": "string", + "format": "date-time", + "additionalProperties": false + } + }, + "required": [ + "systemName", + "stationName", + "itemName", + "stationStock", + "sellPrice", + "demand", + "timestamp" + ] + } + }, + "required": [ + "$schemaRef", + "header", + "message" + ], + "definitions" : { + "levelType" : { + "enum": ["Low", "Med", "High"] + } + } +} \ No newline at end of file diff --git a/utils/src/test/resources/emdn/commodity-v.2.json b/utils/src/test/resources/emdn/commodity-v.2.json new file mode 100644 index 0000000..8ad6155 --- /dev/null +++ b/utils/src/test/resources/emdn/commodity-v.2.json @@ -0,0 +1,119 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "http://schemas.elite-markets.net/eddn/commodity/2#", + "type": "object", + "additionalProperties": false, + "properties": { + "$schemaRef": { + "type": "string", + "additionalProperties": false + }, + "header": { + "type": "object", + "additionalProperties": true, + "properties": { + "uploaderID": { + "type": "string", + "additionalProperties": false + }, + "softwareName": { + "type": "string", + "additionalProperties": false + }, + "softwareVersion": { + "type": "string", + "additionalProperties": false + }, + "gatewayTimestamp": { + "type": "string", + "format": "date-time", + "description": "Timestamp upon receipt at the gateway. If present, this property will be overwritten by the gateway; submitters are not intended to populate this property.", + "additionalProperties": false + } + } + }, + "message": { + "type": "object", + "additionalProperties": false, + "properties": { + "systemName": { + "type": "string", + "additionalProperties": false + }, + "stationName": { + "type": "string", + "additionalProperties": false + }, + "timestamp": { + "type": "string", + "format": "date-time", + "additionalProperties": false + }, + "commodities": { + "type": "array", + "additionalProperties": false, + "items": { + "oneOf": [ + { + "type" : "object", + "properties": { + "name": { + "type": "string", + "additionalProperties": false + }, + "buyPrice": { + "type": "integer", + "description": "Price to buy from the market", + "additionalProperties": false + }, + "supply": { + "type": "integer", + "additionalProperties": false + }, + "supplyLevel": { + "$ref": "#/definitions/levelType" + }, + "sellPrice": { + "type": "integer", + "description": "Price to sell to the market", + "additionalProperties": false + }, + "demand": { + "type": "integer", + "additionalProperties": false + }, + "demandLevel": { + "$ref": "#/definitions/levelType" + } + }, + "required": [ + "name", + "buyPrice", + "supply", + "sellPrice", + "demand" + ] + } + ] + } + } + }, + "required": [ + "systemName", + "stationName", + "commodities", + "timestamp" + ] + } + }, + "required": [ + "$schemaRef", + "header", + "message" + ], + "definitions" : { + "levelType" : { + "enum": ["Low", "Med", "High"] + } + } +} \ No newline at end of file diff --git a/utils/src/test/resources/emdn/commodity-v.3.json b/utils/src/test/resources/emdn/commodity-v.3.json new file mode 100644 index 0000000..00bca26 --- /dev/null +++ b/utils/src/test/resources/emdn/commodity-v.3.json @@ -0,0 +1,114 @@ +{ + "$schema" : "http://json-schema.org/draft-04/schema#", + "id" : "http://schemas.elite-markets.net/eddn/commodity/3#", + "type" : "object", + "additionalProperties" : false, + "required": [ "$schemaRef", "header", "message" ], + "properties": { + "$schemaRef": { + "type" : "string" + }, + "header": { + "type" : "object", + "additionalProperties" : true, + "required" : [ "uploaderID", "softwareName", "softwareVersion" ], + "properties" : { + "uploaderID": { + "type" : "string" + }, + "softwareName": { + "type" : "string" + }, + "softwareVersion": { + "type" : "string" + }, + "gatewayTimestamp": { + "type" : "string", + "format" : "date-time", + "description" : "Timestamp upon receipt at the gateway. If present, this property will be overwritten by the gateway; submitters are not intended to populate this property." + } + } + }, + "message": { + "type" : "object", + "additionalProperties" : false, + "required" : [ "system", "station", "timestamp", "commodities" ], + "properties" : { + "system" : { + "$ref" : "#/definitions/systemWithId" + }, + "station" : { + "$ref" : "#/definitions/nameWithId" + }, + "timestamp": { + "type" : "string", + "format" : "date-time" + }, + "commodities": { + "type" : "array", + "minItems" : 1, + "items" : { + "oneOf" : [ + { + "type" : "object", + "additionalProperties" : false, + "required" : [ "name", "buyPrice", "supply", "sellPrice", "demand" ], + "properties" : { + "name": { + "type" :"string", + "minLength" :1 + }, + "id": { + "type" : "integer", + "description" : "If present should be treated by clients as taking precedence over \"name\"" + }, + "buyPrice": { + "type" :"integer", + "description" :"Price to buy from the market" + }, + "supply": { + "type" : "integer" + }, + "supplyLevel": { + "$ref" : "#/definitions/levelType" + }, + "sellPrice": { + "type" : "integer", + "description" : "Price to sell to the market" + }, + "demand":{ + "type":"integer" + }, + "demandLevel":{ + "$ref":"#/definitions/levelType" + } + } + } + ] + } + } + } + } + }, + "definitions": { + "systemWithId" : { + "type" :"object", + "additionalProperties" : false, + "required" : [ "name" ], + "properties" : { + "name" : { "type": "string", "minLength" : 1 }, + "id" : { "type": "integer", "description" : "If present should be treated by clients as taking precedence over \"name\"" }, + "address" : { "type": "integer" } + } + }, + "nameWithId" : { + "type" :"object", + "additionalProperties" : false, + "required" : [ "name" ], + "properties" : { + "name" : { "type": "string", "minLength" : 1 }, + "id" : { "type": "integer", "description" : "If present should be treated by clients as taking precedence over \"name\"" } + } + } + } +} \ No newline at end of file diff --git a/utils/src/test/resources/emdn/v1.json b/utils/src/test/resources/emdn/v1.json new file mode 100644 index 0000000..a1796e3 --- /dev/null +++ b/utils/src/test/resources/emdn/v1.json @@ -0,0 +1,21 @@ +{ + "$schemaRef": "http://schemas.elite-markets.net/eddn/commodity/1", + "header": { + "uploaderID": "abcdef0123456789", + "softwareName": "My Awesome Market Uploader", + "softwareVersion": "v3.14", + "gatewayTimestamp": "2014-11-17T13:35:00+00:00" + }, + "message": { + "systemName": "Eranin", + "stationName": "Azeban Orbital", + "itemName": "Gold", + "buyPrice": 1024, + "stationStock": 7, + "supplyLevel": "Low", + "sellPrice": 1138, + "demand": 42, + "demandLevel": "Med", + "timestamp": "2014-11-17T12:34:56+00:00" + } +} \ No newline at end of file diff --git a/utils/src/test/resources/emdn/v1e.json b/utils/src/test/resources/emdn/v1e.json new file mode 100644 index 0000000..a9114bf --- /dev/null +++ b/utils/src/test/resources/emdn/v1e.json @@ -0,0 +1,13 @@ +{ + "$schemaRef": "http://schemas.elite-markets.net/eddn/commodity/1", + "header": { + }, + "message": { + "itemName": "Gold", + "buyPrice": 1024, + "stationStock": 7, + "sellPrice": 1138, + "demand": 42, + "timestamp": "2014-11-17T12:34:56+00:00" + } +} \ No newline at end of file diff --git a/utils/src/test/resources/emdn/v1m.json b/utils/src/test/resources/emdn/v1m.json new file mode 100644 index 0000000..dfea54f --- /dev/null +++ b/utils/src/test/resources/emdn/v1m.json @@ -0,0 +1,18 @@ +{ + "$schemaRef": "http://schemas.elite-markets.net/eddn/commodity/1", + "header": { + "uploaderID": "abcdef0123456789", + "softwareName": "My Awesome Market Uploader", + "softwareVersion": "v3.14" + }, + "message": { + "systemName": "Eranin", + "stationName": "Azeban Orbital", + "itemName": "Gold", + "buyPrice": 1024, + "stationStock": 7, + "sellPrice": 1138, + "demand": 42, + "timestamp": "2014-11-17T12:34:56+00:00" + } +} \ No newline at end of file diff --git a/utils/src/test/resources/emdn/v2.json b/utils/src/test/resources/emdn/v2.json new file mode 100644 index 0000000..688a68f --- /dev/null +++ b/utils/src/test/resources/emdn/v2.json @@ -0,0 +1,33 @@ +{ + "$schemaRef": "http://schemas.elite-markets.net/eddn/commodity/2", + "header": { + "uploaderID": "abcdef0123456789", + "softwareName": "My Awesome Market Uploader", + "softwareVersion": "v3.14", + "gatewayTimestamp": "2014-11-17T13:35:00+00:00" + }, + "message": { + "systemName": "Eranin", + "stationName": "Azeban Orbital", + "timestamp": "2014-11-17T12:34:56+00:00", + "commodities": [ + { + "name": "Gold", + "buyPrice": 1024, + "supply": 7, + "supplyLevel": "Low", + "sellPrice": 1138, + "demand": 42, + "demandLevel": "Med" + }, + { + "name": "Explosives", + "buyPrice": 999, + "supply": 1500, + "supplyLevel": "Low", + "sellPrice": 0, + "demand": 0 + } + ] + } +} \ No newline at end of file diff --git a/utils/src/test/resources/emdn/v2e.json b/utils/src/test/resources/emdn/v2e.json new file mode 100644 index 0000000..0296b9d --- /dev/null +++ b/utils/src/test/resources/emdn/v2e.json @@ -0,0 +1,13 @@ +{ + "$schemaRef": "http://schemas.elite-markets.net/eddn/commodity/2", + "header": { + "uploaderID": "abcdef0123456789", + "softwareName": "My Awesome Market Uploader", + "softwareVersion": "v3.14" + }, + "message": { + "systemName": "Eranin", + "stationName": "Azeban Orbital", + "timestamp": "2014-11-17T12:34:56+00:00" + } +} \ No newline at end of file diff --git a/utils/src/test/resources/emdn/v2m.json b/utils/src/test/resources/emdn/v2m.json new file mode 100644 index 0000000..37864b1 --- /dev/null +++ b/utils/src/test/resources/emdn/v2m.json @@ -0,0 +1,22 @@ +{ + "$schemaRef": "http://schemas.elite-markets.net/eddn/commodity/2", + "header": { + "uploaderID": "abcdef0123456789", + "softwareName": "My Awesome Market Uploader", + "softwareVersion": "v3.14" + }, + "message": { + "systemName": "Eranin", + "stationName": "Azeban Orbital", + "timestamp": "2014-11-17T12:34:56+00:00", + "commodities": [ + { + "name": "Gold", + "buyPrice": 1024, + "supply": 7, + "sellPrice": 1138, + "demand": 42 + } + ] + } +} \ No newline at end of file