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