Skip to content

Commit 206901c

Browse files
committed
Working on #374
1 parent 6f13b80 commit 206901c

File tree

12 files changed

+312
-14
lines changed

12 files changed

+312
-14
lines changed

moneta-convert/moneta-convert-ecb/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
</parent>
1010
<artifactId>moneta-convert-ecb</artifactId>
1111
<packaging>jar</packaging>
12+
<properties>
13+
<maven.compiler.source>17</maven.compiler.source>
14+
<maven.compiler.target>17</maven.compiler.target>
15+
</properties>
1216
<dependencies>
1317
<dependency>
1418
<groupId>org.javamoney.moneta</groupId>

moneta-convert/moneta-convert-ecb/src/main/java/org/javamoney/moneta/convert/ecb/ECBAbstractRateProvider.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.javamoney.moneta.convert.ecb;
1717

1818
import org.javamoney.moneta.convert.ExchangeRateBuilder;
19+
import org.javamoney.moneta.convert.ecb.model.Exchange;
1920
import org.javamoney.moneta.spi.AbstractRateProvider;
2021
import org.javamoney.moneta.spi.DefaultNumberValue;
2122
import org.javamoney.moneta.spi.loader.LoadDataInformation;
@@ -35,11 +36,15 @@
3536
import javax.xml.parsers.SAXParser;
3637
import javax.xml.parsers.SAXParserFactory;
3738
import java.io.InputStream;
39+
import java.io.InputStreamReader;
40+
import java.io.Reader;
3841
import java.math.MathContext;
42+
import java.net.URL;
3943
import java.nio.charset.StandardCharsets;
4044
import java.time.LocalDate;
4145
import java.time.format.DateTimeFormatter;
4246
import java.util.Comparator;
47+
import java.util.List;
4348
import java.util.Map;
4449
import java.util.Objects;
4550
import java.util.concurrent.ConcurrentHashMap;
@@ -83,9 +88,11 @@ abstract class ECBAbstractRateProvider extends AbstractRateProvider implements
8388

8489
private final ProviderContext context;
8590

91+
protected final String remoteResource;
8692

87-
ECBAbstractRateProvider(ProviderContext context) {
93+
ECBAbstractRateProvider(ProviderContext context, final String remoteRes) {
8894
super(context);
95+
this.remoteResource = remoteRes;
8996
this.context = context;
9097
saxParserFactory.setNamespaceAware(false);
9198
saxParserFactory.setValidating(false);
@@ -109,19 +116,28 @@ abstract class ECBAbstractRateProvider extends AbstractRateProvider implements
109116

110117
@Override
111118
public void newDataLoaded(String resourceId, InputStream is) {
119+
final ECBUnmarshaller unmarshaller = new ECBUnmarshaller();
112120
final int oldSize = this.rates.size();
113121
try {
122+
//final ExchangeRateParser erp = new ExchangeRateParser(is, getContext().getText());
114123
final SAXParser parser = saxParserFactory.newSAXParser();
115124
//parser.parse(is, new ECBRateReadingHandler(rates, getContext()));
116125

117-
XMLReader xmlReader = parser.getXMLReader();
118-
xmlReader.setContentHandler(new ECBRateReadingHandler(rates, getContext()));
126+
//XMLReader xmlReader = parser.getXMLReader();
127+
//xmlReader.setContentHandler(new ECBRateReadingHandler(rates, getContext()));
119128

120-
final InputSource source = new InputSource(is);
129+
//final InputSource source = new InputSource(is);
130+
//List<Exchange> exchanges = unmarshaller.apply(remoteResource);
121131

122132
// different encoding
123-
source.setEncoding(StandardCharsets.UTF_8.displayName());
124-
xmlReader.parse(source);
133+
//source.setEncoding(StandardCharsets.UTF_8.displayName());
134+
//xmlReader.parse(source, new ECBRateReadingHandler(rates, getContext()));
135+
136+
//Reader isr = new InputStreamReader(is);
137+
//InputSource src = new InputSource();
138+
//src.setCharacterStream(isr);
139+
InputSource src = new InputSource(new URL(remoteResource).openStream());
140+
parser.parse(src, new ECBRateReadingHandler(rates, getContext()));
125141

126142
int newSize = this.rates.size();
127143
loadState = "Loaded " + resourceId + " exchange rates for days:" + (newSize - oldSize);
@@ -177,7 +193,7 @@ private RateResult findExchangeRate(ConversionQuery conversionQuery) {
177193
}
178194
}
179195
String datesOnErros = Stream.of(dates).map(date -> date.format(DateTimeFormatter.ISO_LOCAL_DATE)).collect(Collectors.joining(","));
180-
throw new MonetaryException("There is not exchange on day " + datesOnErros + " to rate to rate on ECBRateProvider.");
196+
throw new MonetaryException("There is no exchange on day " + datesOnErros + " to rate to rate on ECBRateProvider.");
181197
}
182198

183199

moneta-convert/moneta-convert-ecb/src/main/java/org/javamoney/moneta/convert/ecb/ECBCurrentRateProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class ECBCurrentRateProvider extends ECBAbstractRateProvider {
5454
.set("days", 1).build();
5555

5656
public ECBCurrentRateProvider() {
57-
super(CONTEXT);
57+
super(CONTEXT, ECB_CURRENT_URL);
5858
}
5959

6060
@Override

moneta-convert/moneta-convert-ecb/src/main/java/org/javamoney/moneta/convert/ecb/ECBHistoric90RateProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public class ECBHistoric90RateProvider extends ECBAbstractRateProvider {
5858
.set("providerDescription", "European Central Bank (last 90 days)").set("days", 90).build();
5959

6060
public ECBHistoric90RateProvider() {
61-
super(CONTEXT);
61+
super(CONTEXT, ECB_HIST90_URL);
6262
}
6363

6464
@Override

moneta-convert/moneta-convert-ecb/src/main/java/org/javamoney/moneta/convert/ecb/ECBHistoricRateProvider.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import java.util.HashMap;
2828
import java.util.Map;
2929

30+
import static org.javamoney.moneta.convert.ecb.defaults.Defaults.ECB_HIST_URL;
31+
3032
/**
3133
* <p>
3234
* This class implements an {@link javax.money.convert.ExchangeRateProvider}
@@ -61,7 +63,7 @@ public class ECBHistoricRateProvider extends ECBAbstractRateProvider {
6163
.set("providerDescription", "European Central Bank").set("days", 1500).build();
6264

6365
public ECBHistoricRateProvider() {
64-
super(CONTEXT);
66+
super(CONTEXT, ECB_HIST_URL);
6567
}
6668

6769
@Override
@@ -80,8 +82,8 @@ protected LoadDataInformation getDefaultLoadData() {
8082
.withUpdatePolicy(LoaderService.UpdatePolicy.SCHEDULED)
8183
.withProperties(props)
8284
.withBackupResource(URI.create("org/javamoney/moneta/convert/ecb/defaults/eurofxref-hist.xml"))
83-
.withResourceLocations(URI.create("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml"))
84-
.withStartRemote(true)
85+
.withResourceLocations(URI.create(ECB_HIST_URL))
86+
.withStartRemote(false)
8587
.build();
8688
}
8789

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package org.javamoney.moneta.convert.ecb;
2+
3+
import org.javamoney.moneta.convert.ecb.model.Exchange;
4+
import org.w3c.dom.Document;
5+
import org.w3c.dom.NamedNodeMap;
6+
import org.w3c.dom.Node;
7+
import org.w3c.dom.NodeList;
8+
import org.xml.sax.InputSource;
9+
10+
import javax.xml.parsers.DocumentBuilder;
11+
import javax.xml.parsers.DocumentBuilderFactory;
12+
import java.io.InputStream;
13+
import java.io.StringReader;
14+
import java.math.BigDecimal;
15+
import java.net.URL;
16+
import java.nio.charset.StandardCharsets;
17+
import java.time.LocalDate;
18+
import java.time.format.DateTimeFormatter;
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
import java.util.function.Function;
22+
23+
/**
24+
* Created by woorea on 03/04/2017.
25+
*/
26+
public class ECBUnmarshaller implements Function<String, List<Exchange>> {
27+
28+
@Override
29+
public List<Exchange> apply(final String xml) {
30+
31+
//InputSource inputSource = new InputSource (new StringReader(xml));
32+
//InputSource inputSource = new InputSource (xmlStream);
33+
// different encoding
34+
//inputSource.setEncoding(StandardCharsets.UTF_8.displayName());
35+
//inputSource.setCharacterStream();
36+
37+
38+
List<Exchange> exchanges = new ArrayList<>();
39+
40+
try {
41+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
42+
DocumentBuilder db = dbf.newDocumentBuilder();
43+
//Document document = db.parse(inputSource);
44+
Document document = db.parse(new URL(xml).openStream());
45+
46+
document.getDocumentElement().normalize();
47+
48+
Node rootCube = document.getElementsByTagName("Cube").item(0);
49+
50+
NodeList dates = rootCube.getChildNodes();
51+
52+
for(int i = 0; i < dates.getLength(); i++) {
53+
Node dailyNode = dates.item(i);
54+
if(dailyNode.getNodeType() == Node.ELEMENT_NODE) {
55+
NamedNodeMap dailyNodeAttributes = dailyNode.getAttributes();
56+
String timeAttributeValue = dailyNodeAttributes.getNamedItem("time").getNodeValue();
57+
LocalDate localDate = LocalDate.parse(timeAttributeValue, DateTimeFormatter.ISO_LOCAL_DATE);
58+
NodeList exchangeNodeList = dailyNode.getChildNodes();
59+
for (int j = 0; j < exchangeNodeList.getLength(); j++) {
60+
Node exchangeNode = exchangeNodeList.item(j);
61+
if (exchangeNode.getNodeType() == Node.ELEMENT_NODE) {
62+
NamedNodeMap exchangeNodeAttributes = exchangeNode.getAttributes();
63+
String currency = exchangeNodeAttributes.getNamedItem("currency").getNodeValue();
64+
String value = exchangeNodeAttributes.getNamedItem("rate").getNodeValue();
65+
Exchange exchange = new Exchange(localDate, currency, new BigDecimal(value));
66+
exchanges.add(exchange);
67+
}
68+
}
69+
}
70+
}
71+
} catch (Exception e) {
72+
e.printStackTrace();
73+
}
74+
75+
return exchanges;
76+
77+
}
78+
79+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package org.javamoney.moneta.convert.ecb;
2+
3+
import org.javamoney.moneta.convert.ecb.model.Exchange2;
4+
5+
import java.util.logging.Logger;
6+
7+
import javax.xml.stream.XMLInputFactory;
8+
import javax.xml.stream.XMLStreamConstants;
9+
import javax.xml.stream.XMLStreamReader;
10+
import java.io.InputStream;
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
/**
15+
* Parser for ECB XML Feed
16+
* */
17+
public class ExchangeRateParser {
18+
19+
private static final Logger LOGGER = Logger.getLogger(ExchangeRateParser.class.getName());
20+
21+
/**
22+
* Use STaX events to parse the XML feed
23+
* @param xml InputStream of XML test
24+
* @param currency String of currency to find in the XML
25+
* @return List of Exchange2 items
26+
*/
27+
public List<Exchange2> parseRates(InputStream xml, String currency) {
28+
List<Exchange2> rates = new ArrayList<>();
29+
30+
try {
31+
XMLInputFactory factory = XMLInputFactory.newInstance();
32+
XMLStreamReader r = factory.createXMLStreamReader(xml);
33+
try {
34+
int event = r.getEventType();
35+
String date = null;
36+
boolean matchCurrency = false;
37+
boolean continueParse = true;
38+
while (continueParse) {
39+
if (event == XMLStreamConstants.START_ELEMENT) {
40+
// Both the date and rates use the Cube element
41+
if (r.getLocalName().equals("Cube")) {
42+
for(int i = 0, n = r.getAttributeCount(); i < n; ++i) {
43+
// First mark the date
44+
if (r.getAttributeLocalName(i).equals("time")) {
45+
date = r.getAttributeValue(i);
46+
}
47+
48+
// Now get the currency
49+
if ((r.getAttributeLocalName(i).equals("currency")) && r.getAttributeValue(i).equals(currency)) {
50+
matchCurrency = true;
51+
}
52+
53+
// Finally, get the rate and add to the list
54+
if (r.getAttributeLocalName(i).equals("rate")) {
55+
if (matchCurrency) {
56+
Exchange2 rate = new Exchange2(date, currency, Double.parseDouble(r.getAttributeValue(i)));
57+
rates.add(rate);
58+
matchCurrency = false;
59+
}
60+
61+
}
62+
}
63+
}
64+
}
65+
66+
if (!r.hasNext()) {
67+
continueParse = false;
68+
} else {
69+
event = r.next();
70+
}
71+
}
72+
} finally {
73+
r.close();
74+
}
75+
} catch (Exception e) {
76+
LOGGER.severe("Error parsing XML: " + e.getMessage());
77+
}
78+
79+
return rates;
80+
}
81+
}

moneta-convert/moneta-convert-ecb/src/main/java/org/javamoney/moneta/convert/ecb/defaults/Defaults.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ private Defaults() {}
1010

1111
public static final String ECB_HIST90_FALLBACK_PATH = "org/javamoney/moneta/convert/ecb/defaults/eurofxref-hist-90d.xml";
1212

13+
public static final String ECB_HIST_URL = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml";
1314
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package org.javamoney.moneta.convert.ecb.model;
2+
3+
import java.math.BigDecimal;
4+
import java.time.LocalDate;
5+
6+
/**
7+
* Created by woorea on 03/04/2017.
8+
*/
9+
public class Exchange {
10+
11+
private LocalDate date;
12+
13+
private String currency;
14+
15+
private BigDecimal rate;
16+
17+
public Exchange() {
18+
}
19+
20+
public Exchange(LocalDate date, String currency, BigDecimal rate) {
21+
this.date = date;
22+
this.currency = currency;
23+
this.rate = rate;
24+
}
25+
26+
public LocalDate getDate() {
27+
return date;
28+
}
29+
30+
public void setDate(LocalDate date) {
31+
this.date = date;
32+
}
33+
34+
public String getCurrency() {
35+
return currency;
36+
}
37+
38+
public void setCurrency(String currency) {
39+
this.currency = currency;
40+
}
41+
42+
public BigDecimal getRate() {
43+
return rate;
44+
}
45+
46+
public void setRate(BigDecimal rate) {
47+
this.rate = rate;
48+
}
49+
50+
@Override
51+
public boolean equals(Object o) {
52+
if (this == o) return true;
53+
if (o == null || getClass() != o.getClass()) return false;
54+
55+
Exchange exchange = (Exchange) o;
56+
57+
if (!date.equals(exchange.date)) return false;
58+
return currency.equals(exchange.currency);
59+
}
60+
61+
@Override
62+
public int hashCode() {
63+
int result = date.hashCode();
64+
result = 31 * result + currency.hashCode();
65+
return result;
66+
}
67+
}

0 commit comments

Comments
 (0)