Madness and the TableModel

What follows is a lengthy rant about a particularly annoying situation in some of my code. Programmers, please let me know – is it the toolkit that is mad, or is it me? Everyone else, feel free to skip it! :)

For one of my current Java projects, I am using a toolkit that comes with its own complete set of GUI widgets based on Swing. Swing… and horror.

I was under the impression that managing a table in any sane OO language goes a bit like this:

  1. Create a class that roughly represents, or at least holds the data for, a row of the table.
  2. Create a “Table Model” or some other kind of backing array to hold objects of that class.
  3. Create a Table widget that uses the table model as its data source.
  4. Happily filter and sort away, knowing that the model and the view are completely separate entities.

And if you should want to serialise the data behind the table to disk, and load it again, you can just save and reload the model, then call some update method on the table itself to let it know that the model has changed.

Bring on the horror!

What this toolkit does, allegedly in the name of MVC, is this:

  1. Create a class that roughly represents, or at least holds the data for, a row of the table.
  2. Create a “Table Model”, but completely ignore it.
  3. Name the columns of the table after the internal member variables of the class you have created.
  4. Add each object to the table in turn, watching in agony as it extracts the values of those member variables, and puts them into the table as Strings, discarding the original object in the process.

But wait, what if those member variables are (sensibly) private? Oh, no worries. It uses reflection, each and every time you add an object to the table, to figure out what the getter method for that variable is called.

And then we come to wanting to serialise the data to disk. Well, that could be a problem – the table doesn’t contain the objects we want, only Strings. Oh, no worries. You can give the table a new instance of your object, have it figure out (again, at runtime) which the appropriate setter methods are, and run those to make your object again!

Oh, hey, I hope that object didn’t contain any variables that weren’t in the table. ‘Cos if so, you’re not getting them back.

Luckily in my case, everything I care about is shown in the table, which only leaves the attempt to serialise it.

Now I want to have a single class that nicely encapsulates this serialising business for all tables, regardless of what the objects expressed in that table are. Normally, one could just serialise the TableModel and be done with it, but now we need to dynamically re-make the objects based on what’s in the table.

For a fully encapsulated solution, I really want to be able to just pass in the table and have the serialiser take care of the difficult stuff. i.e. I want to call:

if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
    SerialisedTableFile f = new SerialisedTableFile(fc.getSelectedFile());
    f.save(table);
}

But I can’t, because f.save() now has no idea what kind of object it is supposed to be building. So we need to pass f.save() a template object of the class that it is supposed to be building, the only requirement of which is that it can be cloned to produce the real object that we want to store data from the table in. So we implement the Cloneable interface — except that Cloneable doesn’t actually include clone() for some no-doubt genius reason. (Not sarcasm, I really do suspect that language designers are an order of magnitude more intelligent than I.)

The end result of all this is that I now have an interface that delights in the name ReallyCloneable, which all classes that I wrangle into tables have to implement. And poor old f.save() looks like this:

public boolean save(Table table, ReallyCloneable itemTemplate) {
    boolean success = false;
    try {
        if (file.exists()) {
            file.delete();
        }
        if (file.createNewFile()) {
            ArrayList<Object> items = new ArrayList<Object>();
            for (int i = 0; i < table.getRowCount(); i++) {
                try {
                    Object o = itemTemplate.clone();
                    table.getItemFromRow(o, i);
                    items.add(o);
                } catch (NoSuchMethodException ex) {
                    Logger.getLogger(SerialisedTableFile.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    Logger.getLogger(SerialisedTableFile.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
            out.writeObject(items);
            out.close();
            success = true;
        }
    } catch (Exception ex) {
        Logger.getLogger(SerialisedTableFile.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        return success;
    }
}

I think it’s about time I started buying Bad Code Offsets by Direct Debit.

De-Li’s Little Mistake

Oh boy. Yet again, a children’s television programme has driven me to the brink of insanity. I return bearing this. The worst thing of all is that I’m sober, though I have the sudden desire not to be.

If you haven’t watched Waybuloo before, you should probably experience the saccharine horror on iPlayer before reading this travesty.

Crack-crack-crack, came the noise from the sky.

“Look! Whizz-cracker!” said Lau-Lau, and the other Piplings joined her to watch.

“That not whizz-cracker,” said De-Li.

“Not whizz-cracker?”

“Not whizz-cracker. 90-millimetre anti-aircraft gun.”

“Oh. Pretty 90-millimetre anti-aircraft gun.”

Just then, the Piplings heard the familiar chimes of the mystical device that somehow controlled their lives, and like every other day, they were compelled to obey its call.

“Yogo?” asked Yojojo.

“Yogo!”

“Debate finer points of anti-aircraft warfare after Yogo,” said De-Li.

And off they went.

Lined up in front of the nameless device, each Pipling took their allotted turn in the ritual, announcing a shape into which they would have to contort themselves.

“Tree!” said Nok-Tok. And they tried to look like trees.

“Shell!” said De-Li. And they tried to look like shells.

“Monkey!” said Yojojo, which all the others thought was probably cheating. But the machine was watching, so they did it anyway.

“Fish!” said Lau-Lau. They tried to look like fish.

Then, at long last, the device began to chime its song again. It had been appeased for now, and the Piplings tiptoed quietly out of the clearing in case it heard them and summoned them back to dance once more for its entertainment.

Back near their houses, the Piplings were looking out again at what lay beyond their tiny verdant world.

“Why rest of Nara so brown?” asked Nok-Tok.

“Cheebie last week say End Times coming,” said Yojojo. “Cheebie parents say something about ‘Jee-sus’.”

“Lau-Lau wonder why Cheebies leave, go back to brown place,” said Lau-Lau.

“Cheebies say something about ‘Soma’ wearing off,” said Yojojo. “Cheebies go back to get more.”

“Oh,” said Nok-Tok. “Make sense.”

Another noise entered the Piplings’ world from across the horizon — this time, a more human noise.

“Cheebies?” asked Yojojo.

“Cheebies!” exclaimed Lau-Lau. But they turned and looked, and didn’t see quite what they were expecting to see.

“Why Cheebies so old?” asked Nok-Tok.

“Why Cheebies carry assault rifles?” asked De-Li.

“Play Peeka?” asked Lau-Lau, who was always a little slow on the up-take.

“Yes, Lau-Lau,” said De-Li. “Play Peeka right now. Play Peeka really, really well.”

So the Piplings hid themselves in logs and pots and up trees, not sure what to make of the new kind of Cheebies they had seen.

It soon became clear that, not being five-year-olds asked to look for CGI creatures they couldn’t see, the new Cheebies had somewhat of an unfair advantage when playing Peeka. The Piplings were soon rounded up and made to sit back-to-back in the Yogo clearing.

“What new Cheebies names?” said Lau-Lau, still not fully grasping the situation at hand.

One of the Cheebies stepped forward.

“Sergeant Arrowsmith, US Marine Corp,” he said. “Are you the inhabitants of this place?”

“Lau-Lau not know word in-habbit-uns.”

The sergeant sighed. “Do you live here?”

“Yes!” said Lau-Lau happily. “Piplings live here!”

“And do I understand correctly that you are in possession of a machine known as the ‘Anything Machine’, which is capable of generating any object known to the user?”

“Yes! Anything machine!”

De-Li kicked Lau-Lau’s ankle sharply, and got a gun pointed at her for her trouble.

“Play nice,” said the Marine on the other end of the gun. He sneered down the barrel.

“You will take us to this machine,” said the sergeant.

The Piplings were marched at gunpoint to another clearing, where the Anything Machine sat.

“Good,” said Arrowsmith. “You will now use this machine to produce for me an LGM-30 Minuteman ballistic missile with a single warhead, targeted at Moscow.”

“No!” gasped De-Li, and wished she hadn’t.

“Nok-Tok not know what that is,” Nok-Tok said. “Machine not work when not know what making.”

“The pink one knows, sir,” said the Marine who’d pointed the gun earlier.

“Pink creature,” said the sergeant, pointing his own rifle at Lau-Lau. “Make the fucking missile, or I shoot the stupid one. No tricks.”

De-Li took one look into Lau-Lau’s wide staring eyes, and turned her attention to the machine. A few seconds of thinking, a few seconds of trembling ground and burning air, and off the missile flew into the sky.

They waited, and waited. Minutes passed.

Then, over the horizon, a brilliant flash lit up Nara’s sky.

“Good,” said the sergeant, hefting the Anything Machine onto his shoulder. “Tie the creatures up and make them walk. We’re heading back to base.”

Years later, the once-green patch of Nara was as scorched and blackened as the rest of the land. A gust of wind separated the last of the four glittering crystals from the Yogo device, and it splintered into a thousand tiny pieces on the ground. Never again would it call the Piplings to perform for it — the Piplings were free at last. But the Piplings had not been seen since that day they and the Anything Machine were taken. If they still somehow lived, they were the last things to live on Nara.

An Ode to Sharepoint

At a loss for other, more pleasant subjects to blog about, I will instead write about my nemesis, that being that has brought naught but pain to my life. I speak, of course, of Microsoft Sharepoint.

To upgrade one’s version of Windows — Vista to 7, say — is by and large a pretty painless experience for the home user. Office, likewise — there’s no dread that your Office 2003 files will be completely unopenable in Office 2007. So why is the poor sysadmin not afforded the same easy upgrade path?

In order to move an existing SharePoint Services 2 website to a new network with Microsoft Office Sharepoint Services 2007, one must:

  1. Learn more than is healthy about the workings of Sharepoint and IIS (2 days, d10 SAN)
  2. Back up the original site to disk (using stsadm.exe not smigrate.exe, as the latter is broken) (5 hours, 13 GB)
  3. Install Windows Server, IIS, SQL Server and Sharepoint Services 2 on a new machine (1 hour)
  4. Configure said IIS, SQL and Sharepoint (1 hour)
  5. Restore the Sharepoint site from disk onto the new machine (>8 hours, >120 GB, d10 SAN, fails unrecoverably when out of disk space)
  6. Perform an in-place upgrade to Sharepoint Services 3 (Several hours, 40 GB, may fail unrecoverably)
  7. Back up this site to disk (5 hours, 15 GB)
  8. Configure MOSS 2007 on the destination server (2 hours, 24 Google searches, d10 SAN)
  9. Restore the disk backup to the MOSS 2007 server (5 hours, 40 GB, may fail right at the end if previous step performed incorrectly, d100 SAN if this occurs).
  10. Manually recreate permissions on every Sharepoint site since all the users are now part of a new domain (8 hours, d10 SAN)
  11. Perform a ritual to offer Great Cthulhu the souls of Microsoft’s Sharepoint development team (d30 SAN, remarkably quick by comparison)

I began this task on Tuesday afternoon as a mildly knowledgeable Sharepoint user with virtually no admin experience. By Thursday afternoon, I may have been our company’s most experienced Sharepoint-wrangler. On Friday morning, I started the above procedure. We are now on Step 5. 200 people are expecting to have Sharepoint access tomorrow. They have not a snowball’s chance in R’yleh.