Subversion Repositories ES

Rev

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