Rev 17 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 17 | Rev 18 | ||
---|---|---|---|
1 | /**
|
1 | /**
|
2 | *
|
2 | *
|
3 | */
|
3 | */
|
4 | package de.pointedears.converter.net; |
4 | package de.pointedears.converter.net; |
5 | 5 | ||
6 | import java.io.IOException; |
6 | import java.io.IOException; |
7 | import java.text.DateFormat; |
7 | import java.text.DateFormat; |
8 | import java.text.ParseException; |
8 | import java.text.ParseException; |
9 | import java.text.SimpleDateFormat; |
9 | import java.text.SimpleDateFormat; |
10 | import java.util.Date; |
10 | import java.util.Date; |
11 | import java.util.HashMap; |
11 | import java.util.HashMap; |
12 | 12 | ||
13 | import javax.xml.parsers.DocumentBuilder; |
13 | import javax.xml.parsers.DocumentBuilder; |
14 | import javax.xml.parsers.DocumentBuilderFactory; |
14 | import javax.xml.parsers.DocumentBuilderFactory; |
15 | import javax.xml.parsers.ParserConfigurationException; |
15 | import javax.xml.parsers.ParserConfigurationException; |
16 | import javax.xml.xpath.XPath; |
16 | import javax.xml.xpath.XPath; |
17 | import javax.xml.xpath.XPathConstants; |
17 | import javax.xml.xpath.XPathConstants; |
18 | import javax.xml.xpath.XPathExpression; |
18 | import javax.xml.xpath.XPathExpression; |
19 | import javax.xml.xpath.XPathExpressionException; |
19 | import javax.xml.xpath.XPathExpressionException; |
20 | import javax.xml.xpath.XPathFactory; |
20 | import javax.xml.xpath.XPathFactory; |
21 | 21 | ||
22 | import org.w3c.dom.Document; |
22 | import org.w3c.dom.Document; |
23 | import org.w3c.dom.Element; |
23 | import org.w3c.dom.Element; |
24 | import org.w3c.dom.NodeList; |
24 | import org.w3c.dom.NodeList; |
25 | import org.xml.sax.SAXException; |
25 | import org.xml.sax.SAXException; |
26 | 26 | ||
27 | import android.content.Intent; |
27 | import android.content.Intent; |
28 | import android.util.Log; |
28 | import android.util.Log; |
29 | import android.view.View; |
29 | import android.view.View; |
30 | import android.widget.TextView; |
30 | import android.widget.TextView; |
31 | import de.pointedears.converter.R; |
31 | import de.pointedears.converter.R; |
32 | import de.pointedears.converter.app.CurrenciesActivity; |
32 | import de.pointedears.converter.app.CurrenciesActivity; |
33 | import de.pointedears.converter.db.ConversionData; |
33 | import de.pointedears.converter.db.ConversionData; |
34 | import de.pointedears.converter.helpers.ConverterThread; |
34 | import de.pointedears.converter.helpers.ConverterThread; |
35 | import de.pointedears.converter.helpers.UpdateService; |
35 | import de.pointedears.converter.helpers.UpdateService; |
36 | 36 | ||
37 | /**
|
37 | /**
|
38 | * @author pelinux
|
38 | * @author pelinux
|
39 | *
|
39 | *
|
40 | */
|
40 | */
|
41 | public class RatesUpdater implements Runnable |
41 | public class RatesUpdater implements Runnable |
42 | {
|
42 | {
|
- | 43 | /*
|
|
- | 44 | * XML markup attributes
|
|
- | 45 | */
|
|
- | 46 | private static final String ATTR_RATE = "rate"; //$NON-NLS-1$ |
|
- | 47 | private static final String ATTR_CURRENCY = "currency"; //$NON-NLS-1$ |
|
- | 48 | private static final String ATTR_TIME = "time"; //$NON-NLS-1$ |
|
- | 49 | ||
43 | private static final String URL_ECB = |
50 | private static final String URL_ECB = |
44 | "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"; //$NON-NLS-1$ |
51 | "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"; //$NON-NLS-1$ |
45 | 52 | ||
46 | private final CurrenciesActivity activityContext; |
53 | private final CurrenciesActivity activityContext; |
47 | private ConverterThread updateThread = null; |
54 | private ConverterThread updateThread = null; |
48 | 55 | ||
49 | private final UpdateService service; |
56 | private final UpdateService service; |
50 | 57 | ||
51 | /**
|
58 | /**
|
- | 59 | * @param activityContext
|
|
- | 60 | * The activityContext for this updater.
|
|
- | 61 | * FIXME: Required only for database access
|
|
52 | * @param updateService
|
62 | * @param updateService
|
53 | *
|
63 | * The service that started this updater
|
54 | */
|
64 | */
|
55 | public RatesUpdater(CurrenciesActivity activityContext, |
65 | public RatesUpdater(CurrenciesActivity activityContext, |
56 | UpdateService updateService)
|
66 | UpdateService updateService)
|
57 | {
|
67 | {
|
58 | this.activityContext = activityContext; |
68 | this.activityContext = activityContext; |
59 | this.service = updateService; |
69 | this.service = updateService; |
60 | }
|
70 | }
|
61 | 71 | ||
62 | /**
|
72 | /**
|
63 | * @return the updateThread
|
73 | * @return the updateThread
|
64 | */
|
74 | */
|
65 | public ConverterThread getUpdateThread() |
75 | public ConverterThread getUpdateThread() |
66 | {
|
76 | {
|
67 | return this.updateThread; |
77 | return this.updateThread; |
68 | }
|
78 | }
|
69 | 79 | ||
70 | /**
|
80 | /**
|
71 | * @param updateThread
|
81 | * @param updateThread
|
- | 82 | * the thread that this updater is running in
|
|
72 | */
|
83 | */
|
73 | public void setUpdateThread(ConverterThread updateThread) |
84 | public void setUpdateThread(ConverterThread updateThread) |
74 | {
|
85 | {
|
75 | this.updateThread = updateThread; |
86 | this.updateThread = updateThread; |
76 | }
|
87 | }
|
77 | 88 | ||
78 | /*
|
89 | /*
|
79 | * (non-Javadoc)
|
90 | * (non-Javadoc)
|
80 | *
|
91 | *
|
81 | * @see java.lang.Runnable#run()
|
92 | * @see java.lang.Runnable#run()
|
82 | */
|
93 | */
|
83 | @Override |
94 | @Override |
84 | public void run() |
95 | public void run() |
85 | {
|
96 | {
|
86 | int len = 0; |
97 | int len = 0; |
87 | DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$ |
98 | DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$ |
88 | Date updated = new Date(); |
99 | Date updated = new Date(); |
89 | 100 | ||
90 | if (this.getUpdateThread() != null) |
101 | if (this.getUpdateThread() != null) |
91 | {
|
102 | {
|
92 | TextView textUpdating = |
103 | TextView textUpdating = |
93 | (TextView) this.activityContext |
104 | (TextView) this.activityContext |
94 | .findViewById(R.id.currencies_text_updating); |
105 | .findViewById(R.id.currencies_text_updating); |
95 | textUpdating.setVisibility(View.VISIBLE); |
106 | textUpdating.setVisibility(View.VISIBLE); |
96 | 107 | ||
97 | DocumentBuilderFactory documentBuilderFactory = |
108 | DocumentBuilderFactory documentBuilderFactory = |
98 | DocumentBuilderFactory.newInstance(); |
109 | DocumentBuilderFactory.newInstance(); |
99 | documentBuilderFactory.setNamespaceAware(true); |
110 | documentBuilderFactory.setNamespaceAware(true); |
100 | DocumentBuilder builder; |
111 | DocumentBuilder builder; |
101 | try
|
112 | try
|
102 | {
|
113 | {
|
103 | builder = documentBuilderFactory.newDocumentBuilder(); |
114 | builder = documentBuilderFactory.newDocumentBuilder(); |
104 | Document doc; |
115 | Document doc; |
105 | try
|
116 | try
|
106 | {
|
117 | {
|
107 | doc = builder.parse(RatesUpdater.URL_ECB); |
118 | doc = builder.parse(RatesUpdater.URL_ECB); |
108 | XPathFactory xpathFactory = XPathFactory.newInstance(); |
119 | XPathFactory xpathFactory = XPathFactory.newInstance(); |
109 | XPath xpath = xpathFactory.newXPath(); |
120 | XPath xpath = xpathFactory.newXPath(); |
110 | // NamespaceContextHelper namespaceContext =
|
121 | // NamespaceContextHelper namespaceContext =
|
111 | // new NamespaceContextHelper();
|
122 | // new NamespaceContextHelper();
|
112 | // namespaceContext.add("gesmes",
|
123 | // namespaceContext.add("gesmes",
|
113 | // "http://www.gesmes.org/xml/2002-08-01");
|
124 | // "http://www.gesmes.org/xml/2002-08-01");
|
114 | // xpath.setNamespaceContext(namespaceContext);
|
125 | // xpath.setNamespaceContext(namespaceContext);
|
115 | 126 | ||
116 | try
|
127 | try
|
117 | {
|
128 | {
|
118 | /*
|
129 | /*
|
119 | * FIXME: Why doesn't a simple "./Cube/Cube/Cube" work even with a
|
130 | * FIXME: Why doesn't a simple "./Cube/Cube/Cube" work even with a
|
120 | * namespace resolver?
|
131 | * namespace resolver?
|
121 | */
|
132 | */
|
122 | @SuppressWarnings("nls") |
133 | @SuppressWarnings("nls") |
123 | XPathExpression expr = |
134 | XPathExpression expr = |
124 | xpath |
135 | xpath |
125 | .compile("./*[local-name() = 'Cube']/*[local-name() = 'Cube']"); |
136 | .compile("./*[local-name() = 'Cube']/*[local-name() = 'Cube']"); |
126 | NodeList nodes = (NodeList) |
137 | NodeList nodes = (NodeList) |
127 | expr.evaluate(doc.getDocumentElement(), XPathConstants.NODESET); |
138 | expr.evaluate(doc.getDocumentElement(), XPathConstants.NODESET); |
128 | Element parentCube = (Element) nodes.item(0); |
139 | Element parentCube = (Element) nodes.item(0); |
129 | if (parentCube == null) |
140 | if (parentCube == null) |
130 | {
|
141 | {
|
131 | return; |
142 | return; |
132 | }
|
143 | }
|
133 | 144 | ||
134 | try
|
145 | try
|
135 | {
|
146 | {
|
- | 147 | updated = |
|
136 | updated = df.parse(parentCube.getAttribute("time")); |
148 | df.parse(parentCube.getAttribute(RatesUpdater.ATTR_TIME)); |
137 | }
|
149 | }
|
138 | catch (ParseException e) |
150 | catch (ParseException e) |
139 | {
|
151 | {
|
140 | Log.e(this.getClass().toString(), |
152 | Log.e(this.getClass().toString(), |
141 | "Could not parse the `time' attribute into a Date", e); |
153 | "Could not parse the `time' attribute into a Date", e); //$NON-NLS-1$ |
142 | }
|
154 | }
|
143 | 155 | ||
144 | expr = |
156 | expr = |
145 | xpath |
157 | xpath |
146 | .compile("./*[local-name()='Cube' and (@currency='CHF' or @currency='USD')]"); //$NON-NLS-1$ |
158 | .compile("./*[local-name()='Cube' and (@currency='CHF' or @currency='USD')]"); //$NON-NLS-1$ |
147 | nodes = |
159 | nodes = |
148 | (NodeList) expr.evaluate(parentCube, XPathConstants.NODESET); |
160 | (NodeList) expr.evaluate(parentCube, XPathConstants.NODESET); |
149 | NodeList childCubes = nodes; |
161 | NodeList childCubes = nodes; |
150 | 162 | ||
151 | len = childCubes.getLength(); |
163 | len = childCubes.getLength(); |
152 | 164 | ||
153 | HashMap<String, ConversionData> conversionRates = |
165 | HashMap<String, ConversionData> conversionRates = |
154 | this.activityContext.getConversionRates(); |
166 | this.activityContext.getConversionRates(); |
155 | for (int i = 0; i < len; ++i) |
167 | for (int i = 0; i < len; ++i) |
156 | {
|
168 | {
|
157 | Element item = (Element) childCubes.item(i); |
169 | Element item = (Element) childCubes.item(i); |
158 | String currency = item.getAttribute("currency"); |
170 | String currency = item.getAttribute(RatesUpdater.ATTR_CURRENCY); |
159 | 171 | ||
160 | try
|
172 | try
|
161 | {
|
173 | {
|
162 | Double rate = |
174 | Double rate = |
163 | Double.parseDouble(item.getAttribute("rate")); //$NON-NLS-1$ |
175 | Double.parseDouble(item.getAttribute(RatesUpdater.ATTR_RATE)); |
164 | conversionRates |
176 | conversionRates |
165 | .put(currency, new ConversionData(rate, updated)); |
177 | .put(currency, new ConversionData(rate, updated)); |
166 | }
|
178 | }
|
167 | catch (NumberFormatException e) |
179 | catch (NumberFormatException e) |
168 | {
|
180 | {
|
169 | 181 | ||
170 | }
|
182 | }
|
171 | }
|
183 | }
|
172 | 184 | ||
173 | this.activityContext.getDatabase().writeConversionsToDatabase(null); |
185 | this.activityContext.getDatabase().writeConversionsToDatabase(null); |
174 | this.activityContext.fillTableRates(); |
- | |
175 | }
|
186 | }
|
176 | catch (XPathExpressionException e) |
187 | catch (XPathExpressionException e) |
177 | {
|
188 | {
|
178 | Log.e(this.getClass().toString(), "Error in XPath expression", e); |
189 | Log.e(this.getClass().toString(), "Error in XPath expression", e); //$NON-NLS-1$ |
179 | }
|
190 | }
|
180 | }
|
191 | }
|
181 | catch (SAXException e) |
192 | catch (SAXException e) |
182 | {
|
193 | {
|
183 | Log.e(this.getClass().toString(), |
194 | Log.e(this.getClass().toString(), |
184 | "Exception while parsing external XML resource", e); |
195 | "Exception while parsing external XML resource", e); //$NON-NLS-1$ |
185 | }
|
196 | }
|
186 | catch (IOException e) |
197 | catch (IOException e) |
187 | {
|
198 | {
|
188 | Log.e(this.getClass().toString(), |
199 | Log.e(this.getClass().toString(), |
189 | "I/O exception while parsing external XML resource", e); |
200 | "I/O exception while parsing external XML resource", e); //$NON-NLS-1$ |
190 | }
|
201 | }
|
191 | }
|
202 | }
|
192 | catch (ParserConfigurationException e) |
203 | catch (ParserConfigurationException e) |
193 | {
|
204 | {
|
194 | Log.e(this.getClass().toString(), |
205 | Log.e(this.getClass().toString(), |
195 | "Document builder cannot be created", e); |
206 | "Document builder cannot be created", e); //$NON-NLS-1$ |
196 | }
|
207 | }
|
197 | 208 | ||
198 | if (len > 0) |
209 | if (len > 0) |
199 | {
|
210 | {
|
200 | /*
|
211 | /*
|
201 | * Notify the activity that we are done (causes a notification to be
|
212 | * Notify the activity that we are done (causes a notification to be
|
202 | * shown)
|
213 | * shown)
|
203 | */
|
214 | */
|
204 | Intent intent = new Intent(UpdateService.ACTION_UPDATE); |
215 | Intent intent = new Intent(UpdateService.ACTION_UPDATE); |
205 | intent.putExtra(UpdateService.EXTRA_NUM_RATES, len); |
216 | intent.putExtra(UpdateService.EXTRA_NUM_RATES, len); |
206 | intent.putExtra(UpdateService.EXTRA_DATE, updated); |
217 | intent.putExtra(UpdateService.EXTRA_DATE, updated); |
207 | this.service.sendBroadcast(intent); |
218 | this.service.sendBroadcast(intent); |
208 | }
|
219 | }
|
209 | 220 | ||
210 | textUpdating.setVisibility(View.GONE); |
221 | textUpdating.setVisibility(View.GONE); |
211 | }
|
222 | }
|
212 | }
|
223 | }
|
213 | }
|
224 | }
|
214 | 225 |