Subversion Repositories ES

Rev

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
}