Trivial Geocoding with Google and Groovy

I’m building a simple Google Maps mashup that will show where I’ve given classes over the past few years. It’s not much, but it’s an easy demonstration of the technology and, even better, an easy way for me to learn the Google Maps API and to play with Groovy some more.

As for Google Maps, the documentation online isn’t bad, but I have a better alternative. Scott Davis wrote an excellent introductory book for the technology called Google Maps API, v2. I bought the eBook at Pragmatic Programmers for a whopping $8.50. I’m glad to have the eBook, but it’s a bit of a shame, too, because I can’t think of a way to get it autographed when I see Scott at the No Fluff, Just Stuff conference in September.

One of the key elements of any Google map is the latitude and longitude of a particular location. To determine that, you need a geocoder, which is an application that turns place names into lat, long pairs. There are many free ones available on the Internet, but since I’m using Google anyway, I figured I might as well take advantage of theirs.

The data is available at a URL with the appropriate query parameters set. That’s an example of a RESTful web service, of course. Here’s the query for the home office of Kousen IT, Inc.:

http://maps.google.com/maps/geo?q=Marlborough,+CT&output=csv&key=xyz…

I’m using the csv response type, which returns a string of the form:

200,4,41.63257,-72.46314

The first element is the response code (200 for ok, 404 for not found, 610 for “you forgot to add in your key,” etc). The second element is the magnification level, and the last two elements are the latitude and longitude desired. There are also response types for XML, JSON, and others.

I’m going to put all my city, state locations in a database table, but just to test it out I wrote the following Groovy script:


def key = 'my Google Maps API key'
def cities = ['Marlborough','Camarillo','Boston','Winston-Salem']
def states = ['CT','CA','MA','NC']
for (i in 0..3) {
    def city = cities[i]
    def state = states[i]
    def query = "q=${city},+${state}&output=csv&key=${key}"
    def url_string = base + '?q=' +
        ',+' + URLEncoder.encode("${city}","UTF-8") +
        ',+' + state + "&output=csv&key=${key}"
    def results = new URL(url_string).text
    println "${city}, ${state}: " + 
        results.split(',')[-2,-1]*.toDouble()
}

I know there are better ways to store and access the data, but as I say I’m going to move to a database soon anyway. I used the URLEncoder class (from Java) to make sure that if I have any cities with spaces in the name (“Los Angeles”) it gets added to the URL in an encoded form (“Los+Angeles”).

The other parts I like are:

  1. Using the split(String) method in the String class to tokenize the String. I’m still used to using the old StringTokenizer class, but since Java 1.5 the split method has been available. I might as well get used to it.
  2. The beautiful array access from the end of the array [-2,-1] rather than from the beginning [2,3]. If they ever add any data to the response, I’m still fine as long as the lat and long are still the last two elements.
  3. Using the “spread-dot” operator to convert each element of the resulting string into a double.

If this code was going to be any longer I’d create a DAO class for the conversion. I might do that anyway, but this was so easy I couldn’t resist just writing it directly. The results were:

Marlborough, CT: [41.63257, -72.46314]
Camarillo, CA: [34.22291, -119.05074]
Boston, MA: [42.35864, -71.05665]
Winston-Salem, NC: [36.0996, -80.24105]

I still can’t get over how much easier it is to do anything in Groovy compared to raw Java. Programming is fun again. 🙂

2 responses to “Trivial Geocoding with Google and Groovy”

  1. Ken, glad you liked Groovy and found it to be fun. The good news about Groovy is that you can do the same thing with different constructs that fit best your logic, for example the cycle may have been written as

    0.upto(3) { … }
    (0..3).each{ … }

    the following one does the same but reads kind of awkward in the context of your code

    4.times { … }

    Keep on Groovying!

  2. Definitely a good point. When I wrote my actual application, I had a Location class, so I just found all the locations and did an “each” on them.

    Cool stuff.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.