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