(dc..bos): Train Stations as a Groovy Range

I’ve been working on a presentation about interesting features in Groovy, and I came up with an example that I like but is probably too long to do in the available time, so I thought I’d show it here. The idea is to illustrate how any class can be made into a Groovy range by implementing the right methods.

Actually, my larger theme is that understanding Groovy (and the Groovy JDK in particular) is helped considerably by thinking about operator overloading. I don’t do a lot of operator overloading in my own code (present example excepted), but it appears all over the place in the Groovy library. I find it helps Java developers understand Groovy better if they know that whenever they see any operator, they should mentally convert it to a method. For example, + is the plus method, – is minus, and, better yet, […] is getAt or putAt and even as is really asType.

This helps Java devs understand that by reading the groovydocs for String, they realize they can do things like:

String s = 'this is a string'
assert 'this' == s[0..3]
assert 'ing' == s[-3..-1]
assert 'gni' == s[-1..-3]
assert 'thisisastring' == s[0..3, 5..6, 8, -6..-1]
assert 'th is a string' == s - 'is'

and so on.

A groovy range is simply two values separated by a pair of dots, as shown in the previous example. Many classes can be used in a range, as in::

assert [1, 2, 3, 4, 5] == 1..5
assert ['a', 'b', 'c'] == 'a'..'c'
Date now = new Date()
Date then = now + 2
assert ['Jun 16', 'Jun 17', 'Jun 18'] == (now..then)*.format('MMM dd')

(Adjust the last one based on when you run the script, of course. And how cool is it that the Groovy JDK adds a format method to the Date class?)

As the most excellent book Groovy in Action points out (2nd edition available through the Manning Early Access Program), any class can be used in a range if it:

  • implements the java.util.Comparable interface
  • has a next method
  • has a previous method

That’s all you need. I wanted to show an example of this, and based on all my traveling I decided to use train stations. Here’s my first pass at it:

class Station implements Comparable<Station> {
    String name
    Station next
    Station previous
    int position
    
    Station next() { next }
    Station previous() { previous }
    
    int compareTo(Station s) {
        this.position - s.position
    }
    String toString() { name }
}

My Station class is really a node in a doubly-linked list. It has a name and pointers to the next station and the previous station. To make the class implement Comparable, I decided to assign each station an integer position as I added it to a track.

My next step was to use put stations together. At first I was going to use an addStation method, and then I realized that’s really what the plus method was all about. So instead I did this:

    Station plus(Station s) {
       s.position = ++position
       s.previous = this
       this.next = s
       return s 
    }

Here’s a script using the Station class:

Station dc = new Station(name:'DC')
Station phl = new Station(name:'PHL')
Station nyc = new Station(name:'NYC')
Station bos = new Station(name:'BOS')

// operator overloading to make a route:
dc + phl + nyc + bos

// Stations are a range in each direction:
def northBound = (dc..bos)*.name
def southBound = (bos..dc)*.name

assert northBound == ['DC', 'PHL', 'NYC', 'BOS']
assert southBound == ['BOS', 'NYC', 'PHL', 'DC']

That’s all there is to it. I could easily add a minus method to Station in order to remove a node, and if I ever have to use this class in a real system I probably will. The position value is only used for comparison, so the actual number doesn’t matter, but I can imagine that if I have to add and remove lots of stations I’ll need some way to make that more rigorous. I also can’t escape the feeling that a better design would involve a Track class to hold the resulting route, but I didn’t need it for this simple demonstration.

Finally, those of us who occasionally travel the Acela route up and down the northeast corridor know that I left out a lot of stations, but I suppose I can dream that someday our trains will be in the same class (no pun intended) as their European or Asian counterparts. 🙂

(Obligatory marketing: My book Making Java Groovy, also available through the Manning Early Access Program, just went out for its 2/3rds review. I hope to be “text complete” by the end of the summer, for a dead treeware release just in time for the holiday gift-giving season.)

Password authentication using Groovy

This week I was at a client site that was about as locked down as any I’ve seen. Personally I find that incredibly short-sighted on the part of the company, but it’s always easier to say no, I suppose.

While it was annoying enough to set up a browser to surf the web, that’s not sufficient to access remote sites programmatically. For example, the client does a daily download of exchange rate data from a central site, which they process and store in a local db. I wanted to demonstrate that using Groovy.

Normally, to use a proxy I set the host and port on the command line. I’ve done that in Java (and Groovy) many times:

groovy -DproxyHost=10.x.x.x -DproxyPort=8080 myscript.groovy

Most of the time, that’s all you need. In this particular case, however, I also needed to submit a username and a password for authentication on the proxy server.

There are several sites that show you how to do that in Java. Here’s one of them, and it shows that you need to extend the java.net.Authenticator class and override the getPasswordAuthentication method. Here’s an example in Java:

import java.net.Authenticator;
import java.net.PasswordAuthentication;

public class MyAuthenticator extends Authenticator {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("username","password".toCharArray());
    }
}

Then, in your program, set the new authenticator as the default.

Authenticator.setDefault(new MyAuthenticator());

and you’re good to go.

Of course, I couldn’t leave it at that. I was teaching a Groovy class anyway, so I wanted to make the solution groovier. Here’s what I ultimately used:

Authenticator.default = {
    new PasswordAuthentication('username','password' as char[])
} as Authenticator

I switched from using the setDefault method to setting a property, and coerced a closure with the required method into the proper class. Since the authentication mechanism only calls the getPasswordAuthentication method, I can use the single closure as the implementation. Normally I use closure coercion for interfaces, and then generally if they only have a single method, but it was too easy in this case to ignore.

Besides, showing the simplicity of the Groovy solution made the demo a teachable moment, which at least tried to make some lemonade out of the paranoid security lemons. My favorite part was how I hard-wired both the username and password directly into the script, in clear text no less. I could have found a way around that, but I was on a guest account anyway and it felt nicely subversive to do so.

%d bloggers like this: