Subversion Repositories ES

Rev

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
}