Modeling inheritance in Mongoose

For my latest hobby project, I am using NodeJS. Working with JavaScript on the server side is super fun, but it has it drawbacks as well. As you might know, JavaScript is not an object oriented language but a functional language and it uses prototypical inheritance instead of class based inheritance. This does not imply, however, that you cannot emulate classes and class based inheritance. Here’s the proof:

function A() {}
A.prototype.doStuff = function() {
    console.log('doing stuff...');
};
function B() {}
B.prototype = new A();
B.prototype.constructor = B;

var a = new A();
var b = new B();

console.log(a instanceof A); // true;
console.log(a instanceof B); // false;
console.log(b instanceof A); // true;
console.log(b instanceof B); // true;

a.doStuff(); // doing stuff...
b.doStuff(); // doing stuff...

If you want to override the behavior of an instance method, just attach the override to the subclass (B.prototype). You can always call super() by invoking it directly, like so:

B.prototype.doStuff = function() {
    A.prototype.doStuff.call(this); 
    // Or: A.prototype.doStuff.apply(this, arguments); which also passes the arguments
};

The call (of apply()) invocation will execute the method A.prototype.doStuff with respect to a certain context (In this case, this).

This is all real fun, but it is useless in Mongoose. Once you start working with Models, the inheritance relationships are lost because of the way Mongoose treats schemas. Luckily, I’ve come up with an elegant solution and it does not involve the mongoose-schema-extend hack.

The project I am working on is an event-based game. The behavior of each event is encapsulated within an Event “subclass”. This scheme corresponds to the Command Design Pattern. For the purpose of replays, all the events are stored in a single collection because a collection-per-eventType approach is clearly not recommendable here. In order to distinguish different event types, there is a discriminator field inside of each event document. Within my execute method, I could just use a switch(this.type) statement but this would result in a terrible shotgun surgery. Instead, I ended up doing this:

var mongoose = require('mongoose'),
    map = {
        DROP: require('./eventHandlers/Drop'),
        PICKUP: require('./eventHandlers/Pickup')
        // ... more event handlers here
    };

var event = new mongoose.Schema({
    date: {
        type: Date,
        default: Date.now
    },
    type: {
        type: String,
        enum: Object.keys(map)
    },
    params: {}
});

event.path('type').validate(function (value) {
    return '' === value;
}, 'No EventType set');

event.methods.execute = function (game) {
    return map[this.type].execute.call(this, game);
};

module.exports = exports = mongoose.model('Event', event);

This way, all event type specific handling behavior is encapsulated inside a single file that looks like this:

module.exports = exports = {
    execute: function (game) {
        // Event handling goes here...
    }
};

This also allows to add other event specific overrides here (I’t thinking of validation because the params property can contain any data, other hooks, etc.). No more shotgun surgery, just register the handler with a discriminator keyword. Working inheritance and no more headaches, all thanks to Object.prototype.call().

Repack Eclipse for Mac OS X

On Mac OS X, applications are packaged in a “special” way. All application code is contained in a folder with a name ending in .app. Finder will run the program inside such folders instead of showing its contents. This is an elegant model: the application is contained in a single folder, which can be dragged around and you don’t need to know which binary you have to execute in order to run the program.

But then there is Eclipse, which completely ruins this philosophy. Eclipse is shipped as a regular folder, with a .app folder inside it. The binary inside the .app folder loads the application code from folders outside the .app folder.

eclipse/
    artifacts.xml
    configuration/
    dropins/
    eclipse
    Eclipse.app/
    epl-v10.html
    features/
    notice.html
    p2/
    plugins/
    readme/

The application is no longer contained, relies on external sources and it looks awful in your /Applications folder. Fortunately, you can very easily repack Eclipse to look just like a regular OS X application. First, lose the eclipse (all lowercase) symlink. You don’t need that anymore. Now move everything from the eclipse folder (except Eclipse.app) to Eclipse.app/Contents/MacOS. Last, you need to modify eclipse.ini, located in Eclipse.app/Contents/MacOS. This file tells Eclipse where the application code resides. When you open this file and look at its contents, you will probably realize very quickly what you need to do. Change the paths for the startup and launcher.library flags so that they read (beware that the versions of your plugins may differ!):

-startup
./plugins/org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar
--launcher.library
./plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.1.200.v20120522-1813

That’s all! You now have a properly packaged Eclipse app for OS X. Everything should work like it used to.

I really don’t know why Eclipse is shipped in this retarded way for OS X. There was a entry for this in their bug tracker once but is now marked resolved, even though it is not.

While you’re at it, you can also change some of these flags. For instance, if you’re developing Android apps, you can speed up ADT by changing the following flags (According to StackOverflow).

-Dosgi.requiredJavaVersion = 1.6
-Xms128m
-Xmx1024m

USB On-The-Go (OTG) on the HTC Flyer Android tablet

About two months ago, I bought myself an android tablet. It had to be a cheap tablet but I did not want to sacrifice battery life or build quality. I ended up buying an HTC Flyer for about 250 euro.

While exploring the product, I discovered USB OTG information in the Settings application (see picture). Intrigued as I was, I opened a tab and searched the Internet for more information. Is it really supported? Does HTC offer the necessary accessories? I could not find the answers to my questions and this explains why I am writing about this.

USB Storage on HTC Flyer

I wanted to get to the bottom of this, so I started a quest to figure this out. At that time I did not have a USB Host OTG cable. For a while, I thought of soldering a converter using regular USB connectors, but the 4th, or ID pin in a USB micro-B connector (which is needed for OTG) is not used in regular USB data cables (Male USB-A/male USB micro-B). The large male A connector has got only four contacts. I searched the web and found two converters for about $2 (including shipping!). I ordered them right away. What is two dollars?!

When they arrived, I tried it. It did not work. No lights, nothing. Kind of disappointed, I put them away. A while later, I stumbled upon a forum post mentioning that the USB port in the Flyer does not produce enough current to power the USB device. I could not believe that I did not think of that.

Using a pen drive, a USB Y-cable (it has two USB-A male connectors and one female) that shipped with some external portable hard drive and a USB charger (probably any adapter with a female USB A connector will do), I tried it again. Great success! The light on the pen drive started blinking and on the tablet a message appeared: “Preparing tablet storage…”. In the settings app, the information of the pen drive became available.

USB Storage on an HTC Flyer

I used Inka File Manager on my tablet to browse the contents of the pen drive. The contents are located in /sdcard/usb (see picture). Even though the setup is rather clumsy, it works like a charm.

USB Storage on an HTC Flyer

But I don’t want to use the OTG functionality to read pen drives. I want to use it to transfer my photos to my tablet during holidays. I bought a Sharkoon Media Reader S (it’s small, light, cheap and it works with most flash storage) and hooked that up in the same way as I did with the pen drive. Again, great success!

Conclusion

It works, but it requires a rather clumsy setup using the following materials:

  • The HTC Flyer, duh
  • a USB OTG converter
  • A USB Y-cable
  • A USB charger
  • Your preferred USB device: for instance a pen drive or a USB card reader

Note: If it does not work right away, don’t panic. Try it again after rebooting your device or try changing the connections. Also, check that the device you are using is formatted properly. The Flyer can only read FAT32 formatted devices. NTFS formatted hard drives don’t work. I tried, without success…

Disclaimer: Normally, none of the above instructions will damage your device. If however, for some reason, your device gets damaged I cannot be held responsible for it. Use these instructions at your own risk!

USB On-The-Go (OTG)

USB On-The-Go, often abbreviated USB OTG, is a specification that allows USB devices such as digital audio players or mobile phones to act as a host allowing a USB flash drive, mouse, or keyboard to be attached and also connecting USB peripherals directly for communication purposes among them. (source: Wikipedia)