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