- Working update thread - Changed to Euro-based conversion because of ECB as data provider - Added XPath namespace helpers in case we can get namespaces working
/trunk/src/com/nwalsh/namespace/package.html |
---|
File deleted |
Property changes: |
Deleted: svn:mime-type |
## -1 +0,0 ## |
-text/plain |
\ No newline at end of property |
Index: src/com/nwalsh/namespace/NamespaceContextHelper.java |
=================================================================== |
--- src/com/nwalsh/namespace/NamespaceContextHelper.java (revision 16) |
+++ src/com/nwalsh/namespace/NamespaceContextHelper.java (nonexistent) |
@@ -1,394 +0,0 @@ |
-/* |
- * The contents of this file are subject to the terms |
- * of the Common Development and Distribution License |
- * (the "License"). You may not use this file except |
- * in compliance with the License. |
- * |
- * You can obtain a copy of the license at |
- * https://jaxp.dev.java.net/CDDLv1.0.html. |
- * See the License for the specific language governing |
- * permissions and limitations under the License. |
- * |
- * When distributing Covered Code, include this CDDL |
- * HEADER in each file and include the License file at |
- * https://jaxp.dev.java.net/CDDLv1.0.html |
- * If applicable add the following below this CDDL HEADER |
- * with the fields enclosed by brackets "[]" replaced with |
- * your own identifying information: Portions Copyright |
- * [year] [name of copyright owner] |
- */ |
- |
-/* |
- * $Id: NamespaceContextHelper.java,v 1.2 2006-03-28 20:54:02 ndw Exp $ |
- * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. |
- * Portions Copyright 2010 Thomas 'PointedEars' Lahn |
- */ |
- |
-package com.nwalsh.namespace; |
- |
-import java.util.Enumeration; |
-import java.util.Hashtable; |
-import java.util.Iterator; |
- |
-import javax.xml.namespace.NamespaceContext; |
- |
-/* |
- * NOTE: Skip XML 1.1 validity tests because we don't want to recompile |
- * org.apache.xerces for Android -- PointedEars |
- */ |
-// import org.apache.xerces.util.XML11Char; |
- |
-/** |
- * Helper implementation of the javax.xml.namespace.NamespaceContext interface. |
- * |
- * <p> |
- * This class implements the JAXP (1.3+) |
- * {@link javax.xml.namespace.NamespaceContext} interface. This is the interface |
- * used by the JAXP XPath APIs to establish namespace bindings for XPath |
- * expressions. |
- * <p> |
- * |
- * <p> |
- * There are two errors (in retrospect) with respect to the namespace context in |
- * the XPath API. First, there's no way to construct a new one. Given an XPath |
- * you can find out what context it is using, but if you want to construct a new |
- * expression, there's no standard class that you can instantiate to build a new |
- * context. Second, the {@link javax.xml.namespace.NamespaceContext} interface |
- * is obviously (again, in retrospect) missing a method that returns an iterator |
- * that will allow you to find <emph>all</emph> the namespace URIs (and/or |
- * prefixes, which would be equivalent) in the context. |
- * </p> |
- * |
- * <p> |
- * This class addresses the first error by providing an object that you can |
- * instantiate that implements the {@link javax.xml.namespace.NamespaceContext} |
- * interface. It's not a <emph>standard</emph> class, but it at least saves you |
- * the trouble of writing it yourself. (Feel free to move it into your own |
- * package, of course.) |
- * </p> |
- * |
- * <p> |
- * There's really no way to address the second error. An interface, like |
- * {@link javax.xml.namespace.NamespaceContext}, is immutable once released into |
- * the wild in the Java platform. (This is a consequence of backwards |
- * compatibility rules.) To really address the problem, we'll have to invent a |
- * new interface or provide an alternative abstract class that implementations |
- * will be required to use, or something. However, as an experiment, this class |
- * implements a couple of extra methods that we might wish had been in the |
- * interface. These methods are carefully identified as non-standard. Having |
- * them here really isn't all that useful because your underlying XPath |
- * implementation isn't likely to return instances of this class. |
- * </p> |
- * |
- * <p> |
- * There are three ways to instantiate this class: |
- * </p> |
- * |
- * <ol> |
- * <li>The no-argument constructor produces an initially empty namespace |
- * context.</li> |
- * <li>Another constructor takes a prefix and URI and produces a namespace |
- * context with that binding.</li> |
- * <li>Finally, there's a constructor that takes a hash of namespace/uri pairs |
- * and produces a namespace context with those initial bindings.</li> |
- * <li>The obvious constructor, one that takes an existing |
- * {@link javax.xml.namespace.NamespaceContext} so that you can extend it, isn't |
- * there because you can't get the current bindings from that interface; see the |
- * aforementioned bug.</li> |
- * </ol> |
- * |
- * <p> |
- * After the object has been instantiated, you can call the |
- * {@link #add(String,String)} method to add additional bindings to the |
- * namespace context. Because I'm not sure how and where the XPath API |
- * implementations might save pointers to the context object, I've imposed a |
- * number of rules designed to make sure that the context remains coherent: |
- * </p> |
- * |
- * <ul> |
- * <li>Namespace bindings can only be added, not removed.</li> |
- * <li>Once a prefix is bound, its binding cannot be changed.</li> |
- * <li>The XML restrictions on the 'xml' prefix, the 'xmlns' prefix, and their |
- * respective namespace URIs are enforced.</li> |
- * <li>Namespace prefixes must be valid NCNames (or "" for the default |
- * namespace). Note that unprefixed element and attribute names in an XPath |
- * expression can <em>never</em> match a name that's in a namespace. In |
- * particular, setting the default namespace won't have that effect.</li> |
- * </ul> |
- * |
- * <p> |
- * Even with these rules, you can't assume that the context is thread safe. |
- * Don't allow it to be changed while someone else is reading it. |
- * </p> |
- * |
- * <p> |
- * <b>Other notes:</b> |
- * </p> |
- * |
- * <ul> |
- * <li>There's no <code>getNamespaceURIs(String prefix)</code> method because |
- * there can be at most one URI bound to any given prefix. Wrapping an interator |
- * around the mapping available with {@link #getNamespaceURI(String)} seemed |
- * silly.</li> |
- * <li>This class relies on {@link org.apache.xerces.util.XML11Char} to test |
- * that the prefixes are valid NCNames. Note that this means that they're valid |
- * XML 1.1 names. XML 1.1 names are a superset of XML 1.0 names and it didn't |
- * seem worth the extra effort that would be required to allow the user to |
- * choose XML 1.0 or XML 1.1. You might not think it's worth the effort to check |
- * at all. Fair enough.</li> |
- * <li>I've used generics here and there to make the JDK 1.5 compiler stop |
- * complaining. Just delete them for JDK 1.4 and everything should work fine.</li> |
- * </ul> |
- * |
- * @author <a href="mailto:Norman.Walsh@Sun.COM">Norman Walsh</a> |
- * @version $Revision: 1.2 $, $Date: 2006-03-28 20:54:02 $ |
- * @see <a href="http://jaxp.dev.java.net/">Java API for XML Processing</a> |
- * @see <a href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames"> Namespaces |
- * in XML</a> |
- * @see <a href="http://www.w3.org/XML/xml-names-19990114-errata"> Namespaces in |
- * XML Errata</a> |
- */ |
-public class NamespaceContextHelper implements NamespaceContext |
-{ |
- private final Hashtable<String, String> ns = new Hashtable<String, String>(); |
- |
- /** |
- * Creates a new instance of NamespaceContextHelper. |
- * |
- * <p> |
- * Creates an empty namespace context. |
- * </p> |
- */ |
- public NamespaceContextHelper() |
- { |
- } |
- |
- /** |
- * Creates a new instance of NamespaceContextHelper. |
- * |
- * <p> |
- * Creates a namespace context with the bindings specified in |
- * <code>initialNamespaces</code>. |
- * </p> |
- */ |
- public NamespaceContextHelper(Hashtable initialNamespaces) |
- { |
- Enumeration keys = initialNamespaces.keys(); |
- while (keys.hasMoreElements()) |
- { |
- String prefix = (String) keys.nextElement(); |
- String uri = (String) initialNamespaces.get(prefix); |
- |
- this.add(prefix, uri); |
- } |
- } |
- |
- /** |
- * Creates a new instance of NamespaceContextHelper. |
- * |
- * <p> |
- * Creates a namespace context with the specified <code>prefix</code> bound to |
- * <code>uri</code>. |
- * </p> |
- */ |
- public NamespaceContextHelper(String prefix, String uri) |
- { |
- this.add(prefix, uri); |
- } |
- |
- /** |
- * Adds a new prefix/uri binding to the namespace context. |
- * |
- * @throws NullPointerException |
- * if the <code>prefix</code> or <code>uri</code> is |
- * <code>null</code>. |
- * @throws IllegalArgumentException |
- * if the caller attempts to change the binding of |
- * <code>prefix</code>, if the caller attempts to bind the prefix " |
- * <code>xml</code>" |
- * or the namespace " |
- * <code>http://www.w3.org/XML/1998/namespace</code>" incorrectly, |
- * if the caller attempts to bind the prefix "<code>xmlns</code>" or |
- * the namespace |
- * "<code>http://www.w3.org/2000/xmlns</code>", or if the |
- * <code>prefix</code> is |
- * not a valid NCName. |
- */ |
- public void add(String prefix, String uri) |
- { |
- if (prefix == null || uri == null) |
- { |
- throw new NullPointerException( |
- "Null prefix or uri passed to NamespaceContextHelper"); |
- } |
- |
- if (this.ns.containsKey(prefix)) |
- { |
- String curURI = this.ns.get(prefix); |
- if (uri.equals(curURI)) |
- { |
- return; |
- } |
- throw new IllegalArgumentException( |
- "Attempt to change binding in NamespaceContextHelper"); |
- } |
- |
- if ("xml".equals(prefix) |
- && !"http://www.w3.org/XML/1998/namespace".equals(uri)) |
- { |
- throw new IllegalArgumentException( |
- "The prefix 'xml' can only be bound to 'http://www.w3.org/XML/1998/namespace' in NamespaceContextHelper"); |
- } |
- |
- if ("http://www.w3.org/XML/1998/namespace".equals(uri) |
- && !"xml".equals(prefix)) |
- { |
- throw new IllegalArgumentException( |
- "The namespace 'http://www.w3.org/XML/1998/namespace' can only have the prefix 'xml' in NamespaceContextHelper"); |
- } |
- |
- if ("xmlns".equals(prefix) |
- || "http://www.w3.org/2000/xmlns".equals(uri)) |
- { |
- throw new IllegalArgumentException( |
- "Neither the prefix 'xmlns' nor the URI 'http://www.w3.org/2000/xmlns' can be bound in NamespaceContextHelper"); |
- } |
- |
- if ("".equals(prefix)) |
- { |
- this.ns.put(prefix, uri); |
- } |
- else |
- { |
- /* |
- * NOTE: Skip XML 1.1 validity tests because we don't want to recompile |
- * org.apache.xerces for Android -- PointedEars |
- */ |
- // if (XML11Char.isXML11ValidNCName (prefix)) { |
- this.ns.put(prefix, uri); |
- // } else { |
- // throw new IllegalArgumentException |
- // ("Prefix is not a valid NCName in NamespaceContextHelper"); |
- // } |
- } |
- } |
- |
- /** Implements the NamespaceContext getNamespaceURI method. */ |
- public String getNamespaceURI(String prefix) |
- { |
- return this.ns.get(prefix); |
- } |
- |
- /** Implements the NamespaceContext getPrefix method. */ |
- public String getPrefix(String namespaceURI) |
- { |
- if (this.ns.containsValue(namespaceURI)) |
- { |
- Enumeration<String> keys = this.ns.keys(); |
- while (keys.hasMoreElements()) |
- { |
- String pfx = keys.nextElement(); |
- String uri = this.ns.get(pfx); |
- if (namespaceURI.equals(uri)) |
- { |
- return pfx; |
- } |
- } |
- } |
- return null; |
- } |
- |
- /** |
- * Implements a <emph>NON STANDARD</emph> method for finding all of the |
- * prefixes |
- * in the namespace context. |
- * |
- * <p> |
- * Returns an iterator over all of the prefixes in the namespace context. Note |
- * that multiple prefixes may be bound to the same URI. |
- * </p> |
- */ |
- public Iterator getPrefixes() |
- { |
- return this.getPrefixes(null); |
- } |
- |
- /** Implements the NamespaceContext getPrefixes method. */ |
- public Iterator getPrefixes(String namespaceURI) |
- { |
- return new NSIterator(this.ns, namespaceURI); |
- } |
- |
- /** |
- * Implements a <emph>NON STANDARD</emph> method for finding all of the |
- * namespace URIs |
- * in the namespace context. |
- * |
- * <p> |
- * Returns an iterator over all of the namespace URIs in the namespace |
- * context. Note that each namespace URI is returned exactly once, even if it |
- * is bound to several different prefixes. |
- * </p> |
- */ |
- public Iterator getNamespaceURIs() |
- { |
- // Make sure each URI is returned at most once... |
- Hashtable<String, String> uriHash = new Hashtable<String, String>(); |
- Enumeration<String> keys = this.ns.keys(); |
- while (keys.hasMoreElements()) |
- { |
- String pfx = keys.nextElement(); |
- String uri = this.ns.get(pfx); |
- if (!uriHash.containsKey(uri)) |
- { |
- uriHash.put(uri, pfx); |
- } |
- } |
- |
- return new NSIterator(uriHash, null); |
- } |
- |
- /** Implements the Iterator interface over namespace bindings. */ |
- private class NSIterator implements Iterator |
- { |
- private Enumeration<String> keys; |
- |
- public NSIterator(Hashtable<String, String> hash, String value) |
- { |
- this.keys = hash.keys(); |
- if (value != null) |
- { |
- // We have to copy the hash to get only the keys that have the specified |
- // value |
- Hashtable<String, String> vHash = new Hashtable<String, String>(); |
- while (this.keys.hasMoreElements()) |
- { |
- String key = this.keys.nextElement(); |
- String val = hash.get(key); |
- if (val.equals(value)) |
- { |
- vHash.put(key, val); |
- } |
- } |
- this.keys = vHash.keys(); |
- } |
- } |
- |
- public boolean hasNext() |
- { |
- return this.keys.hasMoreElements(); |
- } |
- |
- public String next() |
- { |
- return this.keys.nextElement(); |
- } |
- |
- public void remove() |
- { |
- throw new UnsupportedOperationException( |
- "Cannot remove prefix in NamespaceContextHelper"); |
- } |
- } |
- |
-} |
/src/com/nwalsh/namespace/NamespaceContextHelper.java |
---|
Property changes: |
Deleted: svn:mime-type |
## -1 +0,0 ## |
-text/plain |
\ No newline at end of property |
Index: src/de/pointedears/converter/net/RatesUpdater.java |
=================================================================== |
--- src/de/pointedears/converter/net/RatesUpdater.java (revision 16) |
+++ src/de/pointedears/converter/net/RatesUpdater.java (nonexistent) |
@@ -1,179 +0,0 @@ |
-/** |
- * |
- */ |
-package de.pointedears.converter.net; |
- |
-import java.io.IOException; |
- |
-import javax.xml.parsers.DocumentBuilder; |
-import javax.xml.parsers.DocumentBuilderFactory; |
-import javax.xml.parsers.ParserConfigurationException; |
-import javax.xml.xpath.XPath; |
-import javax.xml.xpath.XPathConstants; |
-import javax.xml.xpath.XPathExpression; |
-import javax.xml.xpath.XPathExpressionException; |
-import javax.xml.xpath.XPathFactory; |
- |
-import org.w3c.dom.Document; |
-import org.w3c.dom.NamedNodeMap; |
-import org.w3c.dom.Node; |
-import org.w3c.dom.NodeList; |
-import org.xml.sax.SAXException; |
- |
-import android.app.Notification; |
-import android.app.NotificationManager; |
-import android.app.PendingIntent; |
-import android.content.Context; |
-import android.content.Intent; |
-import de.pointedears.converter.R; |
-import de.pointedears.converter.helpers.ConverterThread; |
- |
-/** |
- * @author pelinux |
- * |
- */ |
-public class RatesUpdater implements Runnable |
-{ |
- private static final String URL_ECB = |
- "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"; //$NON-NLS-1$ |
- |
- private final Context activityContext; |
- private ConverterThread updateThread = null; |
- |
- /** |
- * |
- */ |
- public RatesUpdater(Context activityContext) |
- { |
- this.activityContext = activityContext; |
- } |
- |
- /** |
- * @return the updateThread |
- */ |
- public ConverterThread getUpdateThread() |
- { |
- return this.updateThread; |
- } |
- |
- /** |
- * @param updateThread |
- */ |
- public void setUpdateThread(ConverterThread updateThread) |
- { |
- this.updateThread = updateThread; |
- } |
- |
- /* |
- * (non-Javadoc) |
- * |
- * @see java.lang.Runnable#run() |
- */ |
- @Override |
- public void run() |
- { |
- if (this.getUpdateThread() != null) |
- { |
- // CurrenciesActivity.this.editValue1.setText("42"); |
- |
- DocumentBuilderFactory documentBuilderFactory = |
- DocumentBuilderFactory.newInstance(); |
- documentBuilderFactory.setNamespaceAware(true); |
- try |
- { |
- DocumentBuilder builder = |
- documentBuilderFactory.newDocumentBuilder(); |
- try |
- { |
- Document doc = builder.parse(RatesUpdater.URL_ECB); |
- XPathFactory xpathFactory = XPathFactory.newInstance(); |
- XPath xpath = xpathFactory.newXPath(); |
- // NamespaceContextHelper namespaceContext = |
- // new NamespaceContextHelper(); |
- // namespaceContext.add("gesmes", |
- // "http://www.gesmes.org/xml/2002-08-01"); |
- // xpath.setNamespaceContext(namespaceContext); |
- |
- try |
- { |
- /* |
- * FIXME: Why doesn't a simple "./Cube/Cube/Cube" work even with a |
- * namespace resolver? |
- */ |
- XPathExpression expr = |
- xpath |
- .compile("./*[local-name() = 'Cube']/*[local-name() = 'Cube']/*[local-name() = 'Cube']"); //$NON-NLS-1$ |
- Object result = |
- expr.evaluate(doc.getDocumentElement(), XPathConstants.NODESET); |
- NodeList nodes = (NodeList) result; |
- |
- int len = nodes.getLength(); |
- |
- String ns = Context.NOTIFICATION_SERVICE; |
- NotificationManager mNotificationManager = |
- (NotificationManager) this.activityContext |
- .getSystemService(ns); |
- |
- int icon = R.drawable.icon; |
- CharSequence tickerText = "Found " + len + " nodes!"; |
- long when = System.currentTimeMillis(); |
- |
- Notification notification = |
- new Notification(icon, tickerText, when); |
- |
- Context applicationContext = |
- this.activityContext.getApplicationContext(); |
- CharSequence contentTitle = "Converter"; |
- CharSequence contentText = "Found " + len + " nodes!"; |
- Intent notificationIntent = |
- new Intent(this.activityContext, this.activityContext.getClass()); |
- PendingIntent contentIntent = |
- PendingIntent.getActivity(this.activityContext, 0, |
- notificationIntent, 0); |
- |
- notification.setLatestEventInfo(applicationContext, contentTitle, |
- contentText, |
- contentIntent); |
- |
- // private static final int HELLO_ID = 1; |
- |
- mNotificationManager.notify(1, notification); |
- |
- for (int i = 0; i < len; ++i) |
- { |
- Node item = nodes.item(i); |
- NamedNodeMap attributes = item.getAttributes(); |
- String currency = |
- attributes |
- .getNamedItem("currency").getNodeValue(); //$NON-NLS-1$ |
- String rate = attributes.getNamedItem("rate").getNodeValue(); //$NON-NLS-1$ |
- |
- /* TODO: Update UI */ |
- System.out.println(currency + ": " + rate); //$NON-NLS-1$ |
- } |
- } |
- catch (XPathExpressionException e) |
- { |
- // TODO Auto-generated catch block |
- e.printStackTrace(); |
- } |
- } |
- catch (SAXException e) |
- { |
- // TODO Auto-generated catch block |
- e.printStackTrace(); |
- } |
- catch (IOException e) |
- { |
- // TODO Auto-generated catch block |
- e.printStackTrace(); |
- } |
- } |
- catch (ParserConfigurationException e) |
- { |
- // TODO Auto-generated catch block |
- e.printStackTrace(); |
- } |
- } |
- } |
-} |
/src/de/pointedears/converter/net/RatesUpdater.java |
---|
Property changes: |
Deleted: svn:mime-type |
## -1 +0,0 ## |
-text/plain |
\ No newline at end of property |
Index: src/de/pointedears/converter/app/CurrenciesActivity.java |
=================================================================== |
--- src/de/pointedears/converter/app/CurrenciesActivity.java (revision 16) |
+++ src/de/pointedears/converter/app/CurrenciesActivity.java (revision 15) |
@@ -5,7 +5,6 @@ |
import android.app.Activity; |
import android.os.Bundle; |
-import android.os.Handler; |
import android.text.Editable; |
import android.view.KeyEvent; |
import android.view.Menu; |
@@ -24,8 +23,7 @@ |
import android.widget.TextView; |
import de.pointedears.converter.R; |
import de.pointedears.converter.db.CurrenciesDatabase; |
-import de.pointedears.converter.helpers.ConverterThread; |
-import de.pointedears.converter.net.RatesUpdater; |
+import de.pointedears.converter.helpers.CurrenciesUpdateThread; |
/** |
* Activity that implements currency conversion |
@@ -60,12 +58,8 @@ |
private Spinner spinnerUnit2; |
private CurrenciesDatabase db; |
- private HashMap<String, Double> conversionRates; |
- private ConverterThread updateThread; |
- private Handler handler; |
+ private HashMap<String, HashMap<String, Double>> conversionRates; |
- private RatesUpdater updateRates; |
- |
/** Called when the activity is first created. */ |
@Override |
@@ -192,15 +186,8 @@ |
editValue2.setText(""); |
} |
}); |
- |
- if (this.handler == null) |
- { |
- this.handler = new Handler(); |
} |
- this.updateThread = null; |
- } |
- |
/** |
* Fills the table with currency conversion rates |
*/ |
@@ -209,14 +196,21 @@ |
TableLayout tableRates = |
(TableLayout) this.findViewById(R.id.currencies_table_rates); |
- for (Entry<String, Double> factorEntry : this.conversionRates.entrySet()) |
+ for (String key : this.conversionRates.keySet()) |
{ |
+ for (Entry<String, Double> factorEntry : this.conversionRates.get(key) |
+ .entrySet()) |
+ { |
TableRow row = new TableRow(this); |
TextView columnCurrency1 = new TextView(this); |
- columnCurrency1.setText(factorEntry.getKey()); |
+ columnCurrency1.setText(key); |
row.addView(columnCurrency1); |
+ TextView columnCurrency2 = new TextView(this); |
+ columnCurrency2.setText(factorEntry.getKey()); |
+ row.addView(columnCurrency2); |
+ |
TextView columnRate = new TextView(this); |
columnRate.setText(factorEntry.getValue().toString()); |
row.addView(columnRate); |
@@ -224,6 +218,7 @@ |
tableRates.addView(row); |
} |
} |
+ } |
/** |
* @param value |
@@ -247,34 +242,17 @@ |
Double newValue = value; |
- /* |
- * NOTE: Had to do it the complicated way because somehow the Android SDK |
- * won't get it another way |
- */ |
- Double factorToEuro = null; |
- if (selectedItemValue1 != null) |
+ HashMap<String, Double> mapForCurrency = |
+ this.conversionRates.get(selectedItemValue1); |
+ if (mapForCurrency != null) |
{ |
- factorToEuro = this.conversionRates.get(selectedItemValue1); |
- } |
- |
- if (factorToEuro == null) |
+ Double conversionFactor = mapForCurrency.get(selectedItemValue2); |
+ if (conversionFactor != null) |
{ |
- factorToEuro = 1.0; |
+ newValue *= conversionFactor; |
} |
- |
- Double factorFromEuro = null; |
- if (selectedItemValue2 != null) |
- { |
- factorFromEuro = this.conversionRates.get(selectedItemValue2); |
} |
- if (factorFromEuro == null) |
- { |
- factorFromEuro = 1.0; |
- } |
- |
- newValue = newValue / factorToEuro * factorFromEuro; |
- |
return newValue.toString(); |
} |
@@ -308,45 +286,10 @@ |
switch (item.getItemId()) |
{ |
case R.id.item_options_update: |
- if (this.updateThread == null) |
- { |
- this.updateRates = new RatesUpdater(this); |
- this.updateThread = |
- new ConverterThread(this.updateRates, this.handler); |
- this.updateRates.setUpdateThread(this.updateThread); |
- } |
- |
- try |
- { |
- this.updateThread.start(); |
- // this.editValue1.setText("Gestartet!"); |
- } |
- catch (IllegalThreadStateException e) |
- { |
- // this.editValue1.setText("Bereits gestartet!"); |
- } |
+ Thread updateThread = new CurrenciesUpdateThread(); |
+ updateThread.start(); |
return true; |
- case R.id.item_options_quit: |
- if (this.updateThread != null) |
- { |
- try |
- { |
- this.updateThread.join(); |
- } |
- catch (InterruptedException e) |
- { |
- // TODO Auto-generated catch block |
- } |
- |
- // this.editValue1.setText("Gestoppt -> Warten auf Start"); |
- } |
- else |
- { |
- // this.editValue1.setText("Bereits gestoppt -> Warten auf Start"); |
- } |
- return true; |
- |
default: |
return super.onOptionsItemSelected(item); |
} |
/trunk/src/de/pointedears/converter/helpers/ConverterThread.java |
---|
File deleted |
Property changes: |
Deleted: svn:mime-type |
## -1 +0,0 ## |
-text/plain |
\ No newline at end of property |
Index: src/de/pointedears/converter/helpers/ConverterNamespaceContext.java |
=================================================================== |
--- src/de/pointedears/converter/helpers/ConverterNamespaceContext.java (revision 16) |
+++ src/de/pointedears/converter/helpers/ConverterNamespaceContext.java (nonexistent) |
@@ -1,58 +0,0 @@ |
-package de.pointedears.converter.helpers; |
- |
-import java.util.HashMap; |
-import java.util.Iterator; |
- |
-import javax.xml.XMLConstants; |
-import javax.xml.namespace.NamespaceContext; |
- |
-/** |
- * @author pelinux |
- * |
- */ |
-public final class ConverterNamespaceContext implements NamespaceContext |
-{ |
- private final HashMap<String, String> namespaces = |
- new HashMap<String, String>(); |
- |
- public void add(String prefix, String uri) |
- { |
- this.namespaces.put(prefix, uri); |
- } |
- |
- @Override |
- public Iterator getPrefixes(String namespaceURI) |
- { |
- throw new UnsupportedOperationException(); |
- } |
- |
- @Override |
- public String getPrefix(String namespaceURI) |
- { |
- throw new UnsupportedOperationException(); |
- } |
- |
- @Override |
- public String getNamespaceURI(String prefix) |
- { |
- if (prefix == null) |
- { |
- throw new NullPointerException("Null prefix"); |
- } |
- else |
- { |
- if ("xml".equals(prefix)) |
- { |
- return XMLConstants.XML_NS_URI; |
- } |
- |
- String storedPrefix = this.namespaces.get(prefix); |
- if (storedPrefix != null) |
- { |
- return storedPrefix; |
- } |
- |
- return XMLConstants.NULL_NS_URI; |
- } |
- } |
-} |
\ No newline at end of file |
/src/de/pointedears/converter/helpers/ConverterNamespaceContext.java |
---|
Property changes: |
Deleted: svn:mime-type |
## -1 +0,0 ## |
-text/plain |
\ No newline at end of property |
Index: src/de/pointedears/converter/helpers/CurrenciesUpdateThread.java |
=================================================================== |
--- src/de/pointedears/converter/helpers/CurrenciesUpdateThread.java (nonexistent) |
+++ src/de/pointedears/converter/helpers/CurrenciesUpdateThread.java (revision 15) |
@@ -0,0 +1,105 @@ |
+/** |
+ * Defines a class to update table rates in the background |
+ */ |
+package de.pointedears.converter.helpers; |
+ |
+import java.io.IOException; |
+ |
+import javax.xml.parsers.DocumentBuilder; |
+import javax.xml.parsers.DocumentBuilderFactory; |
+import javax.xml.parsers.ParserConfigurationException; |
+import javax.xml.xpath.XPath; |
+import javax.xml.xpath.XPathConstants; |
+import javax.xml.xpath.XPathExpression; |
+import javax.xml.xpath.XPathExpressionException; |
+import javax.xml.xpath.XPathFactory; |
+ |
+import org.w3c.dom.Document; |
+import org.w3c.dom.NamedNodeMap; |
+import org.w3c.dom.Node; |
+import org.w3c.dom.NodeList; |
+import org.xml.sax.SAXException; |
+ |
+/** |
+ * @author pelinux |
+ * |
+ */ |
+public class CurrenciesUpdateThread extends Thread |
+{ |
+ private static final String URL_ECB = |
+ "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"; //$NON-NLS-1$ |
+ |
+ /** |
+ * Default constructor which sets the runnable |
+ * |
+ * @param runnable |
+ */ |
+ private CurrenciesUpdateThread(Runnable runnable) |
+ { |
+ super(runnable); |
+ } |
+ |
+ /** |
+ * Default constructor |
+ */ |
+ public CurrenciesUpdateThread() |
+ { |
+ this(new Runnable() { |
+ @Override |
+ public void run() |
+ { |
+ DocumentBuilderFactory documentBuilderFactory = |
+ DocumentBuilderFactory.newInstance(); |
+ documentBuilderFactory.setNamespaceAware(true); |
+ try |
+ { |
+ DocumentBuilder builder = |
+ documentBuilderFactory.newDocumentBuilder(); |
+ try |
+ { |
+ Document doc = builder.parse(CurrenciesUpdateThread.URL_ECB); |
+ XPathFactory xpathFactory = XPathFactory.newInstance(); |
+ XPath xpath = xpathFactory.newXPath(); |
+ try |
+ { |
+ XPathExpression expr = xpath.compile("/Cube/Cube//Cube"); //$NON-NLS-1$ |
+ Object result = expr.evaluate(doc, XPathConstants.NODESET); |
+ NodeList nodes = (NodeList) result; |
+ for (int i = 0, len = nodes.getLength(); i < len; i++) |
+ { |
+ Node item = nodes.item(i); |
+ NamedNodeMap attributes = item.getAttributes(); |
+ String currency = |
+ attributes.getNamedItem("currency").getNodeValue(); //$NON-NLS-1$ |
+ String rate = attributes.getNamedItem("rate").toString(); //$NON-NLS-1$ |
+ |
+ /* TODO: Update UI */ |
+ System.out.println(currency + ": " + rate); //$NON-NLS-1$ |
+ } |
+ } |
+ catch (XPathExpressionException e) |
+ { |
+ // TODO Auto-generated catch block |
+ e.printStackTrace(); |
+ } |
+ } |
+ catch (SAXException e) |
+ { |
+ // TODO Auto-generated catch block |
+ e.printStackTrace(); |
+ } |
+ catch (IOException e) |
+ { |
+ // TODO Auto-generated catch block |
+ e.printStackTrace(); |
+ } |
+ } |
+ catch (ParserConfigurationException e) |
+ { |
+ // TODO Auto-generated catch block |
+ e.printStackTrace(); |
+ } |
+ } |
+ }); |
+ } |
+} |
/src/de/pointedears/converter/helpers/CurrenciesUpdateThread.java |
---|
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: src/de/pointedears/converter/db/CurrenciesDatabase.java |
=================================================================== |
--- src/de/pointedears/converter/db/CurrenciesDatabase.java (revision 16) |
+++ src/de/pointedears/converter/db/CurrenciesDatabase.java (revision 15) |
@@ -20,22 +20,36 @@ |
public class CurrenciesDatabase extends SQLiteOpenHelper |
{ |
private static final String DATABASE_NAME = "currency.db"; //$NON-NLS-1$ |
- private static final int DATABASE_VERSION = 3; |
+ private static final int DATABASE_VERSION = 2; |
private static final String TABLE = "currency"; //$NON-NLS-1$ |
- private static final String COLUMN_CURRENCY = "currency1"; //$NON-NLS-1$ |
+ private static final String COLUMN_CURRENCY1 = "currency1"; //$NON-NLS-1$ |
+ private static final String COLUMN_CURRENCY2 = "currency2"; //$NON-NLS-1$ |
private static final String COLUMN_FACTOR = "factor"; //$NON-NLS-1$ |
- private static HashMap<String, Double> conversionRates = |
- new HashMap<String, Double>(); |
+ private static HashMap<String, HashMap<String, Double>> conversionRates = |
+ new HashMap<String, HashMap<String, Double>>(); |
static |
{ |
- /* Default conversion rates from Euro (EUR) to other currencies */ |
- CurrenciesDatabase.conversionRates |
- .put(CurrenciesActivity.VALUE_CHF, 1.3013); |
- CurrenciesDatabase.conversionRates |
- .put(CurrenciesActivity.VALUE_USD, 1.3521); |
+ HashMap<String, Double> conversionFactors = new HashMap<String, Double>(); |
+ conversionFactors.put(CurrenciesActivity.VALUE_EUR, 0.767842293); |
+ conversionFactors.put(CurrenciesActivity.VALUE_USD, 1.03413); |
+ CurrenciesDatabase.conversionRates.put(CurrenciesActivity.VALUE_CHF, |
+ conversionFactors); |
+ |
+ conversionFactors = new HashMap<String, Double>(); |
+ conversionFactors.put(CurrenciesActivity.VALUE_CHF, 1.30235077); |
+ conversionFactors.put(CurrenciesActivity.VALUE_USD, 1.3468); |
+ CurrenciesDatabase.conversionRates.put(CurrenciesActivity.VALUE_EUR, |
+ conversionFactors); |
+ |
+ conversionFactors = new HashMap<String, Double>(); |
+ conversionFactors.put(CurrenciesActivity.VALUE_CHF, 0.966996412); |
+ conversionFactors.put(CurrenciesActivity.VALUE_EUR, 0.742500743); |
+ CurrenciesDatabase.conversionRates.put(CurrenciesActivity.VALUE_USD, |
+ conversionFactors); |
} |
+ private final CurrenciesActivity context; |
/** |
* @param context |
@@ -45,6 +59,7 @@ |
{ |
super(context, CurrenciesDatabase.DATABASE_NAME, null, |
CurrenciesDatabase.DATABASE_VERSION); |
+ this.context = context; |
this.readConversionsFromDatabase(); |
} |
@@ -60,23 +75,30 @@ |
public void onCreate(SQLiteDatabase db) |
{ |
db.execSQL("CREATE TABLE IF NOT EXISTS " + CurrenciesDatabase.TABLE |
- + " (" + CurrenciesDatabase.COLUMN_CURRENCY + " TEXT, " |
+ + " (" + CurrenciesDatabase.COLUMN_CURRENCY1 + " TEXT, " |
+ + CurrenciesDatabase.COLUMN_CURRENCY2 + " TEXT, " |
+ CurrenciesDatabase.COLUMN_FACTOR |
+ " NUMERIC" |
+ ", CONSTRAINT unique_currency_pair UNIQUE (" |
- + CurrenciesDatabase.COLUMN_CURRENCY + "))"); |
+ + CurrenciesDatabase.COLUMN_CURRENCY1 + ", " |
+ + CurrenciesDatabase.COLUMN_CURRENCY2 + "))"); |
- HashMap<String, Double> currencyConversions = |
+ HashMap<String, HashMap<String, Double>> currencyConversions = |
this.getConversionRates(); |
- for (Entry<String, Double> factorEntry : currencyConversions.entrySet()) |
+ for (String key : currencyConversions.keySet()) |
{ |
+ for (Entry<String, Double> factorEntry : currencyConversions.get(key) |
+ .entrySet()) |
+ { |
ContentValues values = new ContentValues(); |
- values.put(CurrenciesDatabase.COLUMN_CURRENCY, factorEntry.getKey()); |
+ values.put(CurrenciesDatabase.COLUMN_CURRENCY1, key); |
+ values.put(CurrenciesDatabase.COLUMN_CURRENCY2, factorEntry.getKey()); |
values.put(CurrenciesDatabase.COLUMN_FACTOR, factorEntry.getValue()); |
db.insert(CurrenciesDatabase.TABLE, CurrenciesDatabase.COLUMN_FACTOR, |
values); |
} |
} |
+ } |
/* |
* (non-Javadoc) |
@@ -97,7 +119,7 @@ |
/** |
* @return |
*/ |
- public HashMap<String, Double> getConversionRates() |
+ public HashMap<String, HashMap<String, Double>> getConversionRates() |
{ |
return CurrenciesDatabase.conversionRates; |
} |
@@ -113,9 +135,11 @@ |
/* Get database connection, but upgrade database first if necessary! */ |
SQLiteDatabase dbConn = this.getWritableDatabase(); |
+ @SuppressWarnings("nls") |
Cursor cursor = |
dbConn.query(true, CurrenciesDatabase.TABLE, null, null, null, null, |
- null, CurrenciesDatabase.COLUMN_CURRENCY, null); |
+ null, CurrenciesDatabase.COLUMN_CURRENCY1 + "," |
+ + CurrenciesDatabase.COLUMN_CURRENCY2, null); |
if (cursor != null) |
{ |
@@ -123,7 +147,10 @@ |
{ |
int currency1Id = |
cursor |
- .getColumnIndexOrThrow(CurrenciesDatabase.COLUMN_CURRENCY); |
+ .getColumnIndexOrThrow(CurrenciesDatabase.COLUMN_CURRENCY1); |
+ int currency2Id = |
+ cursor |
+ .getColumnIndexOrThrow(CurrenciesDatabase.COLUMN_CURRENCY2); |
int factorId = |
cursor.getColumnIndexOrThrow(CurrenciesDatabase.COLUMN_FACTOR); |
@@ -130,17 +157,58 @@ |
/* NOTE: Don't change the default values if the table is empty */ |
if (cursor.moveToFirst()) |
{ |
- HashMap<String, Double> newCurrencyConversions = |
- new HashMap<String, Double>(); |
+ HashMap<String, HashMap<String, Double>> newCurrencyConversions = |
+ new HashMap<String, HashMap<String, Double>>(); |
+ HashMap<String, Double> mapForCurrency = null; |
+ String lastCurrency1Str = null; |
+ String currency1Str; |
do |
{ |
- String currencyStr = cursor.getString(currency1Id); |
+ currency1Str = cursor.getString(currency1Id); |
+ String currency2Str = cursor.getString(currency2Id); |
Double factor = cursor.getDouble(factorId); |
- newCurrencyConversions.put(currencyStr, factor); |
+ |
+ if (lastCurrency1Str == null |
+ || !lastCurrency1Str.equals(currency1Str)) |
+ { |
+ /* |
+ * NOTE: Update outer map when we see a new currency; |
+ * ORDER BY ensures we don't see a currency1 twice except |
+ * consecutively |
+ */ |
+ if (mapForCurrency != null) |
+ { |
+ newCurrencyConversions.put(lastCurrency1Str, mapForCurrency); |
} |
+ |
+ lastCurrency1Str = new String(currency1Str); |
+ |
+ /* NOTE: New currency1: Reset inner map */ |
+ mapForCurrency = newCurrencyConversions.get(currency1Str); |
+ } |
+ |
+ /* If we did not see this currency1 before */ |
+ if (mapForCurrency == null) |
+ { |
+ mapForCurrency = new HashMap<String, Double>(); |
+ } |
+ |
+ /* |
+ * NOTE: Update inner map after each table row; assignment to |
+ * mapForCurrency above ensures we are putting the factor |
+ * into the correct map. |
+ */ |
+ mapForCurrency.put(currency2Str, factor); |
+ } |
while (cursor.moveToNext()); |
+ /* |
+ * NOTE: Update from last table row; cursor not empty, so we can |
+ * skip the test for null |
+ */ |
+ newCurrencyConversions.put(currency1Str, mapForCurrency); |
+ |
CurrenciesDatabase.conversionRates = newCurrencyConversions; |
} |
} |
@@ -169,9 +237,11 @@ |
{ |
SQLiteDatabase dbConn = this.getReadableDatabase(); |
+ @SuppressWarnings("nls") |
Cursor myCursor = |
dbConn.query(true, CurrenciesDatabase.TABLE, null, null, null, null, |
- null, CurrenciesDatabase.COLUMN_CURRENCY, null); |
+ null, CurrenciesDatabase.COLUMN_CURRENCY1 + "," |
+ + CurrenciesDatabase.COLUMN_CURRENCY2, null); |
@SuppressWarnings({ "unused", "nls" }) |
String queryResult = ""; |
@@ -181,7 +251,10 @@ |
{ |
int currency1Id = |
myCursor |
- .getColumnIndexOrThrow(CurrenciesDatabase.COLUMN_CURRENCY); |
+ .getColumnIndexOrThrow(CurrenciesDatabase.COLUMN_CURRENCY1); |
+ int currency2Id = |
+ myCursor |
+ .getColumnIndexOrThrow(CurrenciesDatabase.COLUMN_CURRENCY2); |
int factorId = |
myCursor.getColumnIndexOrThrow(CurrenciesDatabase.COLUMN_FACTOR); |
@@ -189,12 +262,13 @@ |
{ |
do |
{ |
- String currencyStr = myCursor.getString(currency1Id); |
+ String currency1Str = myCursor.getString(currency1Id); |
+ String currency2Str = myCursor.getString(currency2Id); |
Double factor = myCursor.getDouble(factorId); |
/* DEBUG */ |
queryResult += |
- "EUR --> " + currencyStr + ": " + factor + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
+ currency1Str + " --> " + currency2Str + ": " + factor + "\n"; |
} |
while (myCursor.moveToNext()); |
} |
/trunk/bin/Converter.apk |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/bin/resources.ap_ |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/bin/classes.dex |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/res/values/strings.xml |
---|
10,8 → 10,9 |
<string name="temperatures_off_scale"><sup>*</sup> Theoretical value off the scale</string> |
<string name="activity_currencies">Currencies</string> |
<string name="currencies_currency"><b>Currency</b></string> |
<string name="currencies_rate"><b>Rate (1 EUR = ?)</b></string> |
<string name="currencies_currency1"><b>Currency 1</b></string> |
<string name="currencies_currency2"><b>Currency 2</b></string> |
<string name="currencies_rate"><b>Rate</b></string> |
<string name="caption_update">Update table rates</string> |
<string name="option_quit">Quit</string> |
<!-- <string name="option_quit">Quit</string> --> |
</resources> |
/trunk/res/menu/options.xml |
---|
6,6 → 6,8 |
android:title="@string/caption_update" /> |
<!-- android:icon="@drawable/ic_quit" --> |
<item android:id="@+id/item_options_quit" |
<!-- |
<item android:id="@+id/quit" |
android:title="@string/option_quit" /> |
--> |
</menu> |
/trunk/res/layout/activity_currencies.xml |
---|
33,11 → 33,12 |
android:layout_gravity="center_horizontal"></Button> |
<TableLayout android:id="@+id/currencies_table_rates" |
android:scrollbars="vertical" android:layout_height="wrap_content" |
android:layout_width="fill_parent" android:stretchColumns="*"> |
android:layout_height="fill_parent" android:layout_width="fill_parent" |
android:scrollbars="vertical" android:stretchColumns="*"> |
<View android:layout_height="2dip" android:background="#FF909090" /> |
<TableRow> |
<TextView android:text="@string/currencies_currency" /> |
<TextView android:text="@string/currencies_currency1" /> |
<TextView android:text="@string/currencies_currency2" /> |
<TextView android:text="@string/currencies_rate" /> |
</TableRow> |
<View android:layout_height="1dip" android:background="#FF909090" /> |
/trunk/.classpath |
---|
1,6 → 1,6 |
<?xml version="1.0" encoding="UTF-8"?> |
<classpath> |
<classpathentry excluding="com/nwalsh/namespace/" kind="src" path="src"/> |
<classpathentry kind="src" path="src"/> |
<classpathentry kind="src" path="gen"/> |
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> |
<classpathentry kind="output" path="bin"/> |