sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1491236 - in /sis/branches/JDK6: ./ application/sis-app/src/main/java/org/apache/sis/cli/ application/sis-app/src/main/java/org/apache/sis/console/ core/sis-metadata/src/main/java/org/apache/sis/metadata/ storage/sis-storage/src/main/java/...
Date Sun, 09 Jun 2013 16:05:22 GMT
Author: desruisseaux
Date: Sun Jun  9 16:05:22 2013
New Revision: 1491236

URL: http://svn.apache.org/r1491236
Log:
Merge from the JDK7 branch.

Added:
    sis/branches/JDK6/application/sis-app/src/main/java/org/apache/sis/console/
      - copied from r1491235, sis/branches/JDK7/application/sis-app/src/main/java/org/apache/sis/console/
    sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/index/package-info.java
      - copied unchanged from r1491235, sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/index/package-info.java
Removed:
    sis/branches/JDK6/application/sis-app/src/main/java/org/apache/sis/cli/
Modified:
    sis/branches/JDK6/   (props changed)
    sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/package-info.java
    sis/branches/JDK6/pom.xml
    sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java
    sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/index/GeoHashCoderTest.java

Propchange: sis/branches/JDK6/
------------------------------------------------------------------------------
  Merged /sis/branches/JDK7:r1490713-1491235

Modified: sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/package-info.java?rev=1491236&r1=1491235&r2=1491236&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/package-info.java
[UTF-8] (original)
+++ sis/branches/JDK6/core/sis-metadata/src/main/java/org/apache/sis/metadata/package-info.java
[UTF-8] Sun Jun  9 16:05:22 2013
@@ -40,7 +40,7 @@
  * the property name is inferred from the method name like what the <cite>Java Beans</cite>
framework does.</p>
  *
  * <p>The implementation classes, if they exist, are defined in different packages
than the interfaces.
- * For example the ISO 19115 interfaces, declared in {@code org.opengis.metadata}, are implemented
by
+ * For example the ISO 19115 interfaces, declared in {@link org.opengis.metadata}, are implemented
by
  * SIS in {@link org.apache.sis.metadata.iso}. The subpackages hierarchy is the same, and
the names
  * of implementation classes are the name of the implemented interfaces prefixed with {@code
Abstract}
  * or {@code Default}.</p>
@@ -63,7 +63,7 @@
  * {@section How Metadata are handled}
  * Metadata objects in SIS are mostly containers: they provide getter and setter methods
for manipulating the values
  * associated to properties (for example the {@code title} property of a {@code Citation}
object), but provide few logic.
- * The package {@code org.apache.sis.metadata.iso} and its sub-packages are the main examples
of such containers.
+ * The package {@link org.apache.sis.metadata.iso} and its sub-packages are the main examples
of such containers.
  *
  * <p>In addition, the metadata modules provide support methods for handling the metadata
objects through Java Reflection.
  * This is an approach similar to <cite>Java Beans</cite>, in that users are
encouraged to use directly the API of
@@ -72,14 +72,14 @@
  *
  * <p>Using Java reflection, a metadata can be viewed in many different ways:</p>
  * <ul>
- *   <li><b>As a {@link java.util.Map}</b><br>
+ *   <li><p><b>As a {@link java.util.Map}</b><br>
  *       The {@link org.apache.sis.metadata.MetadataStandard} class provides various methods
returning a view
  *       of an arbitrary metadata implementation as a {@code Map}, where the key are the
property names and the
  *       values are the return values, types or descriptions of getter methods. The map is
writable if the
  *       underlying metadata implementation has setter methods, otherwise attempts to set
a value throw an
- *       {@code UnmodifiableMetadataException}.</li>
+ *       {@code UnmodifiableMetadataException}.</p></li>
  *
- *   <li><b>As a {@link org.apache.sis.util.collection.TreeTable}</b><br>
+ *   <li><p><b>As a {@link org.apache.sis.util.collection.TreeTable}</b><br>
  *       The metadata are organized as a tree. For example the {@code Citation} metadata
contains one or many
  *       {@code ResponsibleParty} elements, each of them containing a {@code Contact} element,
which contains
  *       a {@code Telephone} element, <i>etc</i>. For each node, there is many
information that can be displayed
@@ -90,9 +90,9 @@
  *         <li>The range of valid values (if the type is numeric),
  *             or an enumeration of valid values (if the type is a code list).</li>
  *         <li>The value stored in the element, or the default value.</li>
- *       </ul></li>
+ *       </ul></p></li>
  *
- *   <li><b>As a table record in a database (using {@link org.apache.sis.metadata.sql})</b><br>
+ *   <li><p><b>As a table record in a database (using {@link org.apache.sis.metadata.sql})</b><br>
  *       It is possible to establish the following mapping between metadata and a SQL database:
  *       <ul>
  *         <li>Each metadata interface maps to a table of the same name in the database.</li>
@@ -100,7 +100,7 @@
  *         <li>Each instance of the above interface is a record in the above table.</li>
  *       </ul>
  *       Using Java reflection, it is possible to generate implementations of the metadata
interfaces
- *       where each call to a getter method is translated into a SQL query for the above
database.</li>
+ *       where each call to a getter method is translated into a SQL query for the above
database.</p></li>
  * </ul>
  *
  * {@section How Metadata are marshalled}
@@ -109,7 +109,7 @@
  *
  * <p>Only the implementation classes defined in the {@link org.apache.sis.metadata.iso}
packages and sub-packages
  * are annotated for JAXB marshalling. If a metadata is implemented by an other package (for
example
- * {@code org.apache.sis.metadata.sql}), then it shall be converted to an annotated class
before to be marshalled.
+ * {@link org.apache.sis.metadata.sql}), then it shall be converted to an annotated class
before to be marshalled.
  * All SIS annotated classes provide a copy constructor for this purpose. A shallow copy
is sufficient;
  * JAXB adapters will convert the elements on-the-fly when needed.</p>
  *

Modified: sis/branches/JDK6/pom.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/pom.xml?rev=1491236&r1=1491235&r2=1491236&view=diff
==============================================================================
--- sis/branches/JDK6/pom.xml (original)
+++ sis/branches/JDK6/pom.xml Sun Jun  9 16:05:22 2013
@@ -636,6 +636,7 @@ Apache SIS is a free software, Java lang
             <taglet><tagletClass>org.apache.sis.internal.taglet.WebSite</tagletClass></taglet>
             <taglet><tagletClass>org.apache.sis.internal.taglet.Section</tagletClass></taglet>
             <taglet><tagletClass>org.apache.sis.internal.taglet.Note</tagletClass></taglet>
+            <taglet><tagletClass>org.apache.sis.internal.taglet.Example</tagletClass></taglet>
             <taglet><tagletClass>org.apache.sis.internal.taglet.Preformat</tagletClass></taglet>
           </taglets>
           <tagletArtifact>

Modified: sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java?rev=1491236&r1=1491235&r2=1491236&view=diff
==============================================================================
--- sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java
[UTF-8] (original)
+++ sis/branches/JDK6/storage/sis-storage/src/main/java/org/apache/sis/index/GeoHashCoder.java
[UTF-8] Sun Jun  9 16:05:22 2013
@@ -16,9 +16,19 @@
  */
 package org.apache.sis.index;
 
+import java.io.Serializable;
+import java.text.ParseException;
+import org.opengis.geometry.DirectPosition;
+import org.apache.sis.geometry.DirectPosition2D;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.resources.Errors;
+
 
 /**
- * Utilities for encoding and decoding geohashes.
+ * Encodes geographic coordinates as <cite>geohashes</cite> strings, and decode
such strings back to coordinates.
+ * The current implementation is restricted to two-dimensional geographic coordinates, in
the (<var>longitude</var>,
+ * <var>latitude</var>) order with the longitudes ranging from -180° to 180°
and the latitudes ranging from -90° to
+ * 90°. The datum is unspecified.
  *
  * @author  Chris Mattmann (JPL)
  * @since   0.1
@@ -27,146 +37,275 @@ package org.apache.sis.index;
  *
  * @see <a href="http://en.wikipedia.org/wiki/Geohash">Wikipedia: Geohash</a>
  */
-public class GeoHashCoder {
+public class GeoHashCoder implements Serializable {
     /**
-     * The characters used for the 32 bits variant of geohash.
+     * For cross-version compatibility.
      */
-    private static final byte[] ENCODING_32 = {
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-        'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm',
-        'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
-    };
+    private static final long serialVersionUID = 9162259764027168776L;
 
     /**
-     * The reverse of {@link #ENCODING_32}.
+     * The encoding format used by {@link GeoHashCoder}.
      */
-    private static final byte[] DECODING_32 = reverse(ENCODING_32);
+    public static enum Format {
+        /**
+         * Format consisting of 32 symbols used at {@code http://geohash.org}. This encoding
uses digits 0 to 9,
+         * and lower-case letters {@code 'b'} to {@code 'z'} excluding {@code 'i'}, {@code
'l'} and {@code 'o'}.
+         * Decoding is case-insensitive.
+         */
+        BASE32(16, new byte[] {
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+            'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm',
+            'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
+        });
+
+        /**
+         * A single one-bit in the position of the highest-order ("leftmost") one-bit of
the value
+         * represented by a letter or digit. This value can be computed as {@code 1 <<
(numBits-1)}
+         * where {@code numBits} is the number of bits needed for representing a letter or
digit.
+         */
+        final int highestOneBit;
+
+        /**
+         * Mapping from a numerical value to its symbol. The length of this array is the
base of the encoding,
+         * e.g. 32 for {@link #BASE32}.
+         */
+        final byte[] encoding;
+
+        /**
+         * Mapping from a lower-case letter symbols to its numerical value.
+         */
+        final byte[] decodingLowerCase;
+
+        /**
+         * Mapping from a upper-case letter symbols to its numerical value.
+         * This is the same array than {@link #decodingLowerCase} if the format is case-insensitive.
+         */
+        final byte[] decodingUpperCase;
+
+        /**
+         * Creates a new format for the given {@coe encoding} mapping.
+         * This constructor computes the {@code decoding} arrays from the {@code encoding}
one.
+         *
+         * @param highestOneBit The leftmost one-bit of the value represented by a letter
or digit.
+         * @param encoding The mapping from numerical values to symbols.
+         */
+        private Format(final int highestOneBit, final byte[] encoding) {
+            this.highestOneBit = highestOneBit;
+            this.encoding = encoding;
+            final byte[] decoding = new byte[26];
+            for (byte i=10; i<encoding.length; i++) {
+                decoding[encoding[i] - 'a'] = i;
+            }
+            decodingLowerCase = decoding;
+            decodingUpperCase = decoding;
+            // Current version create a case-insensitive format.
+            // However if we implement BASE36 in a future version,
+            // then the two 'decoding' arrays will differ.
+        }
+    }
 
     /**
-     * Creates a decoding array from the given encoding one.
-     * Only the letters are stored in this array, not the digits.
+     * The format used by the {@code GeoHashCoder}.
      */
-    private static byte[] reverse(final byte[] encoding) {
-        final byte[] decoding = new byte[26];
-        for (byte i=10; i<encoding.length; i++) {
-            decoding[encoding[i] - 'a'] = i;
-        }
-        return decoding;
-    }
+    private Format format;
 
     /**
      * Amount of letters or digits to format in the geohash.
+     * Stored as a {@code byte} on the assumption that attempts to create
+     * geohashes of more then 255 characters is likely to be an error anyway.
      */
-    private int precision;
+    private byte precision;
 
-    private static final int[] BITS = { 16, 8, 4, 2, 1 };
+    /**
+     * A buffer of length {@link #precision}, created when first needed.
+     */
+    private transient char[] buffer;
 
     /**
-     * Creates a new geohash coder/decoder initialized to the default precision.
+     * Creates a new geohash coder/decoder initialized to the default precision for {@link
Format#BASE32}.
      */
     public GeoHashCoder() {
+        format = Format.BASE32;
         precision = 12;
     }
 
     /**
-     * Encodes the given latitude and longitude into a geohash.
+     * Returns the current encoding/decoding format.
+     * The default value is {@link Format#BASE32}.
      *
-     * @param latitude
-     *          Latitude to encode
-     * @param longitude
-     *          Longitude to encode
-     * @return Geohash encoding of the longitude and latitude
-     */
-    public String encode(final double latitude, final double longitude) {
-      final double[] latInterval = { -90.0, 90.0 };
-      final double[] lngInterval = { -180.0, 180.0 };
-
-      final StringBuilder geohash = new StringBuilder();
-      boolean isEven = true;
-
-      int bit = 0;
-      int ch = 0;
-
-      while (geohash.length() < precision) {
-        double mid;
-        if (isEven) {
-            mid = (lngInterval[0] + lngInterval[1]) / 2D;
-            if (longitude > mid) {
-                ch |= BITS[bit];
-                lngInterval[0] = mid;
-            } else {
-                lngInterval[1] = mid;
-            }
-        } else {
-            mid = (latInterval[0] + latInterval[1]) / 2D;
-            if (latitude > mid) {
-                ch |= BITS[bit];
-                latInterval[0] = mid;
+     * @return The current format.
+     */
+    public Format getFormat() {
+        return format;
+    }
+
+    /**
+     * Sets the encoding/decoding format.
+     *
+     * @param format The new format.
+     */
+    public void setFormat(final Format format) {
+        ArgumentChecks.ensureNonNull("format", format);
+        this.format = format;
+    }
+
+    /**
+     * Returns the length of geohashes strings to be encoded by the {@link #encode(double,
double)} method.
+     * The default value is 12.
+     *
+     * @return The length of geohashes strings.
+     */
+    public int getPrecision() {
+        return precision;
+    }
+
+    /**
+     * Sets the length of geohashes strings to be encoded by the {@link #encode(double, double)}
method.
+     *
+     * @param precision The new length of geohashes strings.
+     */
+    public void setPrecision(final int precision) {
+        ArgumentChecks.ensureBetween("precision", 1, 255, precision);
+        this.precision = (byte) precision;
+        buffer = null; // Will recreate a new buffer when first needed.
+    }
+
+    /**
+     * Encodes the given longitude and latitude into a geohash.
+     *
+     * @param longitude Longitude to encode, as decimal degrees in the [-180 … 180]° range.
+     * @param latitude Latitude to encode, as decimal degrees in the [-90 … 90]° range.
+     * @return Geohash encoding of the given longitude and latitude.
+     */
+    public String encode(final double longitude, final double latitude) {
+        final byte[] encoding = format.encoding;
+        final int highestOneBit = format.highestOneBit;
+        char[] geohash = buffer;
+        if (geohash == null) {
+            buffer = geohash = new char[precision & 0xFF];
+        }
+        /*
+         * The current implementation assumes a two-dimensional coordinates. The 'isEven'
boolean takes
+         * the 'true' value for longitude, and 'false' for latitude. We could extend this
algorithm to
+         * the multi-dimensional case by replacing 'isEven' by a counter over the ordinate
dimension.
+         */
+        boolean isEven = true;
+        double xmin = -180, ymin = -90;
+        double xmax =  180, ymax =  90;
+        /*
+         * 'ch' is the index of the character to be added in the geohash. The actual character
will be
+         * given by the 'encoding' array. 'bit' shall have a single one-bit, rotating from
10000 in the
+         * BASE32 case to 00001 (binary representation).
+         */
+        int ch = 0;
+        int bit = highestOneBit;
+        for (int i=0; i<geohash.length;) {
+            if (isEven) {
+                final double mid = (xmin + xmax) / 2;
+                if (longitude > mid) {
+                    ch |= bit;
+                    xmin = mid;
+                } else {
+                    xmax = mid;
+                }
             } else {
-                latInterval[1] = mid;
+                final double mid = (ymin + ymax) / 2;
+                if (latitude > mid) {
+                    ch |= bit;
+                    ymin = mid;
+                } else {
+                    ymax = mid;
+                }
             }
-        }
 
-        isEven = !isEven;
+            isEven = !isEven;
 
-        if (bit < 4) {
-            bit++;
-        } else {
-            geohash.append((char) ENCODING_32[ch]);
-            bit = 0;
-            ch = 0;
+            bit >>>= 1;
+            if (bit == 0) {
+                geohash[i++] = (char) encoding[ch];
+                bit = highestOneBit;
+                ch = 0;
             }
         }
-        return geohash.toString();
+        return new String(geohash);
+    }
+
+    /**
+     * Encodes the given position into a geohash. The current implementation takes the first
ordinate value as the
+     * longitude, the second ordinate value as the latitude, then delegates to {@link #encode(double,
double)}.
+     *
+     * <p>The current implementation does not verify the Coordinate Reference System
of the given position.
+     * However this may change in future SIS versions.</p>
+     *
+     * @param  position The coordinate to encode.
+     * @return Geohash encoding of the given position.
+     */
+    public String encode(final DirectPosition position) {
+        ArgumentChecks.ensureDimensionMatches("position", 2, position);
+        return encode(position.getOrdinate(0), position.getOrdinate(1));
     }
 
     /**
-     * Decodes the given geohash into a latitude and longitude
+     * Decodes the given geohash into a longitude and a latitude.
      *
-     * @param geohash
-     *          Geohash to decode
-     * @return Array with the latitude at index 0, and longitude at index 1
+     * @param geohash Geohash string to decode.
+     * @return A new position with the longitude at ordinate 0 and latitude at ordinate 1.
+     * @throws ParseException If an error occurred while parsing the given string.
      */
-    public double[] decode(final String geohash) {
+    public DirectPosition decode(final String geohash) throws ParseException {
         final int length = geohash.length();
-        final double[] latInterval = { -90.0, 90.0 };
-        final double[] lngInterval = { -180.0, 180.0 };
+        final int highestOneBit = format.highestOneBit;
+        final byte[] decodingLowerCase = format.decodingLowerCase;
+        final byte[] decodingUpperCase = format.decodingUpperCase;
+        /*
+         * The current implementation assumes a two-dimensional coordinates. The 'isEven'
boolean takes
+         * the 'true' value for longitude, and 'false' for latitude. We could extend this
algorithm to
+         * the multi-dimensional case by replacing 'isEven' by a counter over the ordinate
dimension.
+         */
         boolean isEven = true;
+        double xmin = -180, ymin = -90;
+        double xmax =  180, ymax =  90;
 
-        int nc;
+        int nc; // Number of characters for the 'c' code point.
         for (int i=0; i<length; i+=nc) {
             int c = geohash.codePointAt(i);
             nc = Character.charCount(c);
-            if (c >= 'a' && c <= 'z') {
-                c = DECODING_32[c - 'a'];
-                if (c == 0) {
-                    throw new IllegalArgumentException(geohash);
-                }
-            } else if (c >= '0' && c <= '9') {
+            if (c >= '0' && c <= '9') {
                 c -= '0';
             } else {
-                throw new IllegalArgumentException(geohash);
+                if (c >= 'a' && c <= 'z') {
+                    c = decodingLowerCase[c - 'a'];
+                } else if (c >= 'A' && c <= 'Z') {
+                    c = decodingUpperCase[c - 'A'];
+                } else {
+                    c = 0;
+                }
+                if (c == 0) {
+                    throw new ParseException(Errors.format(Errors.Keys.UnparsableStringForClass_3,
+                            "GeoHash",geohash, geohash.substring(i, i+nc)), i);
+                }
             }
-            for (int mask : BITS) {
+            int mask = highestOneBit;
+            do {
                 if (isEven) {
+                    final double mid = (xmin + xmax) / 2;
                     if ((c & mask) != 0) {
-                        lngInterval[0] = (lngInterval[0] + lngInterval[1]) / 2D;
+                        xmin = mid;
                     } else {
-                        lngInterval[1] = (lngInterval[0] + lngInterval[1]) / 2D;
+                        xmax = mid;
                     }
                 } else {
+                    final double mid = (ymin + ymax) / 2;
                     if ((c & mask) != 0) {
-                        latInterval[0] = (latInterval[0] + latInterval[1]) / 2D;
+                        ymin = mid;
                     } else {
-                        latInterval[1] = (latInterval[0] + latInterval[1]) / 2D;
+                        ymax = mid;
                     }
                 }
                 isEven = !isEven;
-            }
+            } while ((mask >>>= 1) != 0);
         }
-        double latitude = (latInterval[0] + latInterval[1]) / 2D;
-        double longitude = (lngInterval[0] + lngInterval[1]) / 2D;
-
-        return new double[] { latitude, longitude };
+        return new DirectPosition2D((xmin + xmax) / 2,
+                                    (ymin + ymax) / 2);
     }
 }

Modified: sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/index/GeoHashCoderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/index/GeoHashCoderTest.java?rev=1491236&r1=1491235&r2=1491236&view=diff
==============================================================================
--- sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/index/GeoHashCoderTest.java
[UTF-8] (original)
+++ sis/branches/JDK6/storage/sis-storage/src/test/java/org/apache/sis/index/GeoHashCoderTest.java
[UTF-8] Sun Jun  9 16:05:22 2013
@@ -16,8 +16,8 @@
  */
 package org.apache.sis.index;
 
-import java.util.Map;
-import java.util.HashMap;
+import java.text.ParseException;
+import org.opengis.geometry.DirectPosition;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -42,11 +42,13 @@ public final strictfp class GeoHashCoder
      * A geographic coordinates together with the expected geohash.
      */
     private static final class Place {
-        final double latitude;
+        final String name;
         final double longitude;
+        final double latitude;
         final String geohash;
 
-        Place(final double latitude, final double longitude, final String geohash) {
+        Place(final String name, final double longitude, final double latitude, final String
geohash) {
+            this.name      = name;
             this.latitude  = latitude;
             this.longitude = longitude;
             this.geohash   = geohash;
@@ -54,19 +56,17 @@ public final strictfp class GeoHashCoder
     }
 
     /**
-     * Returns a map of places with their expected geohash.
+     * A list o places with their expected geohash.
      */
-    private Map<String, Place> places() {
-        final Map<String, Place> places = new HashMap<String, Place>(12);
-        places.put("Empire State Building", new Place(40.748433,  -73.985656, "dr5ru6j2c62q"));
-        places.put("Statue Of Liberty",     new Place(40.689167,  -74.044444, "dr5r7p4rx6kz"));
-        places.put("The White House",       new Place(38.897669,  -77.036550, "dqcjqcpeq70c"));
-        places.put("Hoover Dam",            new Place(36.015556, -114.737778, "9qqkvh6mzfpz"));
-        places.put("Golden Gate Bridge",    new Place(37.819722, -122.478611, "9q8zhuvgce0m"));
-        places.put("Mount Rushmore",        new Place(43.878947, -103.459825, "9xy3teyv7ke4"));
-        places.put("Space Needle",          new Place(47.620400, -122.349100, "c22yzvh0gmfy"));
-        return places;
-    }
+    private static Place[] PLACES = new Place[] {
+        new Place("Empire State Building",  -73.985656, 40.748433, "dr5ru6j2c62q"),
+        new Place("Statue Of Liberty",      -74.044444, 40.689167, "dr5r7p4rx6kz"),
+        new Place("The White House",        -77.036550, 38.897669, "dqcjqcpeq70c"),
+        new Place("Hoover Dam",            -114.737778, 36.015556, "9qqkvh6mzfpz"),
+        new Place("Golden Gate Bridge",    -122.478611, 37.819722, "9q8zhuvgce0m"),
+        new Place("Mount Rushmore",        -103.459825, 43.878947, "9xy3teyv7ke4"),
+        new Place("Space Needle",          -122.349100, 47.620400, "c22yzvh0gmfy")
+    };
 
     /**
      * Tests the {@link GeoHashCoder#encode(double, double)} method.
@@ -74,25 +74,23 @@ public final strictfp class GeoHashCoder
     @Test
     public void testEncode() {
         final GeoHashCoder coder = new GeoHashCoder();
-        for (final Map.Entry<String, Place> entry : places().entrySet()) {
-            final Place place = entry.getValue();
-            assertEquals(entry.getKey(), place.geohash,
-                    coder.encode(place.latitude, place.longitude));
+        for (final Place place : PLACES) {
+            assertEquals(place.name, place.geohash, coder.encode(place.longitude, place.latitude));
         }
     }
 
     /**
      * Tests the {@link GeoHashCoder#decode(String)} method.
+     *
+     * @throws ParseException Should never happen.
      */
     @Test
-    public void testDecode() {
+    public void testDecode() throws ParseException {
         final GeoHashCoder coder = new GeoHashCoder();
-        for (final Map.Entry<String, Place> entry : places().entrySet()) {
-            final String name = entry.getKey();
-            final Place place = entry.getValue();
-            final double[] result = coder.decode(place.geohash);
-            assertEquals(name, place.latitude,  result[0], TOLERANCE);
-            assertEquals(name, place.longitude, result[1], TOLERANCE);
+        for (final Place place : PLACES) {
+            final DirectPosition result = coder.decode(place.geohash);
+            assertEquals(place.name, place.longitude, result.getOrdinate(0), TOLERANCE);
+            assertEquals(place.name, place.latitude,  result.getOrdinate(1), TOLERANCE);
         }
     }
 }



Mime
View raw message