Atom Feed SITE FEED   ADD TO GOOGLE READER

Thoughts on Predicates and/or Matchers

Rob is working on making filter development easier. Currently whenever a user wants to do some custom filtering, they need to extend our AbstractFilterList and implement its filterMatches(Object) method. This gets the job done but there's some problems:
  • Discourages code reuse from the filterMatches() method
  • Reinventing the wheel: many users will end up implementing common requirements like a filterMatches() that tests if an element is in some other list.
  • Slow: implicitly pairs one AbstractFilterList (and associated costs) for every matching strategy
  • Not dynamic: filterMatches() method does not lend itself to different behaviour over time

    Therefore we're building something smarter using predicates, or as we like to call them, Matchers. Since Matchers aren't exactly predicates, the name-change makes sense. For example, rarely do predicates fire events when their match logic is modified!

    Matchers are great. We can build in a library of ready-to-use matchers for common tasks such as:
  • Testing for equality with any object, null or otherwise. Via '==' or even '.equals()'
  • Testing for containment in some other set
  • Comparison to a constant.
  • Thresholds
  • instanceof, .getClass()
  • Composition of multiple matchers with AND, OR, NOT, XOR etc.
  • Delegate matchers. I can delegate to another matcher using an extracted bean property of the tested object.

    Of course the above Matchers stuff will require a lot of code! Rob's written a lot of it already, but I have this (irrational?) fear that we're getting away from our 'core competency'. Why is this a problem?
  • That code is going to want to be maintaned! It will require at least one huge effort when we migrate to Java 5.
  • We're all-of-the-sudden becoming a toolkit for more than list transformations. From here it would seem natural to add Closures as well, since they are necessary for building delegation-capable predicates.
  • There's already at least three open source predicate toolkits. They're all incompatible with different merits and design goals. We will simply be yet another incompatible implementation to add to the mix. Adapters simplify this problem, but there are limitations! For example, no other predicates toolkit that I found used events to send notification of a mutation. And this feature is a must for our implementation!

    So what is the solution? Obviously matchers are a good thing and we want them in our code. Rob is a hell of a coder and he's dedicated to matchers, so most of my complaints about the required effort are muted. But I still think we're getting away from our core-competency! Yuck.
  • Notes on variable-height rows in a JTable

    Recently Sun hosted a developer web chat, Getting High Performance from Your Desktop Client. I decided to ask about a problem I faced a few months ago: performance of JTables with variable-height rows.

    The Premise
    To track the heights of each row, JTable uses a SizeSequence. This class stores the height of each row in pixels, plus it includes helper methods to answer common questions, "What row belongs in pixel P?" and "What's pixel range for row R?". To make answering these questions snappy, the SizeSequence precomputes the answers and stores them in an array.

    The Problem
    Suppose we add, remove or change the height of a row in our JTable. Now our SizeSequence's answers array is out of sync. Unfortunately the SizeSequence must recalculate the entire answers array. For a table with R rows, this will require R operations!

    The Problem Multiplies
    Suppose our table is populated one row at a time. This will be the case for all applications where the rows are streamed or filtered. Now this is R changes, each one requiring R operations to update the SizeSequence. For a table with R rows, this will require R2 operations!

    Workaround 1
    Don't use variable row height JTables!

    Workaround 2
    Bulk up row changes. Instead of adding rows one at a time, add them ten at a time or better, all at once.

    Workaround 3
    Go have a coffee and wait for Sun to resolve issue 6231057. This should shorten the cost of a row change from R operations to a much more tolerable log2R.

    Simple mail trick for good or evil

    My mail client (Mail.app) allows me to configure which email headers get displayed. I set it up to display some extra headers for my own novelty...

    X-Mailer: display the Mail client program used to craft a given email. This is mostly for my own curiosity. If somebody is using a Mac, I might ask them if they're upgrading to OS X Tiger. If they're using Outlook, I'll think twice about opening the screensaver attachments!

    X-Originating-Ip: this header appears in Hotmail.com messages. It gives the IP address of the sending user. I can use this to probe for FTP servers, SSH servers and the like on my friend's machines. For non-hotmail users, this IP address is usually found in the last of the Received: headers.

    32 bit file sizes in Apache HTTPD

    Today I backed up some files from my Powerbook to a DVD image. Once I created the DVD image I was going to transfer it to my PC which is the home of my burner. How shall I transfer the file?
  • Via SMB? Nope. I've had very little success with SMB in the past, and I think it's slow
  • Via FTP? Nope. The Windows FTP command sucks wind.
  • Via HTTP? Sure! My Mac has Apache built-in, and then I can download with my browser. This combination might even support resume if the transfer is interrupted.

    I dumped the DVD image in my ~/Sites/ folder, which is the Mac-equivalent of ~/public_html. But when I viewed that directory from my PC, the 4.37 GB file morphed into a 386 MB file. What the heck?

    And now a math lesson. My file was 4.37 GB. More precisely: 4699488256 bytes. And unfortunately for me, 4699488256 > (232). In fact, 4.37 GB mod (232) = 386 MB.

    Lesson learned? Apache file sizes are 32-bit. Don't transfer anything larger than 4 GB over the web!