Refactoring Encoding/Decoding on the BKTable

BKit.jpg

Today I spent a few hours refactoring the encoding and decoding on the BKTable because I wanted to achieve two things, neither of which was a pressing need for the BKTable: First, to allow the inclusion of the Vector as an elemental data type in the contents of a table's cell, and two: to expose the encoding and decoding of the Vector (Array) so that the CKit-based tables and Lists will match up nicely. The genesis of this is really to be able to have an applet PARAM tag take a Vector so that it's easy for a person to generate that tag (using the encoding of a Vector), and it's easy for me to decode it.

What this ended up doing was to really overhaul the serialization methods for the BKTable and make them look a lot more like their CKit counterparts. The finding of an appropriate delimiter is important to the table, but it's also important to the list. So the old way of having it embedded into the table's encode was just not the right thing to do. Likewise, the way in which individual values were both encoded and decoded was too restrictive for what I needed.

In the end, it was a few hours that gave me some very interesting code snippets. The most interesting, was the thread-safe, thread-local SimpleDateFormat. The Date, as an element in the table needed to be able to be decoded and encoded. But the SimpleDateFormat is not thread-safe, so what's to be done? The old code had a new one created for each encoding and decoding. The new one uses the code below:

  /**
   * In order to make the formatting of Date values efficient,
   * I want to make a class that's going to handle the formatting
   * in a thread-safe way using thread-local storage. The idea is
   * that each thread will create it's own formatter, and then
   * there won't be need for a bunch of them, and there won't be
   * problems with excessive garbage collection.
   */
  class SafeDateFormatter {
    private static ThreadLocal formatter = new ThreadLocal() {
      protected synchronized Object initialValue() {
        return new SimpleDateFormat("yyyyMMdd.hhmmss");
      }
    };
 
    public static String format(Date arg) {
      return ((SimpleDateFormat) formatter.get()).format(arg);
    }
 
    public static Date parse(String arg) {
      return ((SimpleDateFormat) formatter.get()).parse(arg,
            new ParsePosition(0));
    }
  }

with this little jewel, the incoming thread will create a thread-local copy of the SimpleDateFormatter with the default formatter provided. Then, each call after that will use the one and not create another. This is something I can see that they might not have wanted to do, but I can't imagine how much garbage collection I would have had were I to blindly create one each time one was needed. Yikes.

When I got all this done I created a few more tests, and like a champ, they worked perfectly. I was very happy. But all this did was really set the stage for the changes to the BKSimpleScatterGraphApplet - the ability to pre-select the z-axis values from an applet tag.