Issue 47

Added getAll(), putAll() and removeAll() implementations with reader and writer support. The code in the cache layer should be versatile enough so that the store layer has a lot of flexibility on how it wants to load the keys.
I just realized that there's a bug - not really here but in the integration of this method with `OnHeapStore.bulkCompute`, _if_ instead of mocking the store in your unit test `EhcacheBulkMethodsTest`, you wire in OnHeapStore implementation. `OnHeapStore.bulkCompute()` will not cause new entries to be written out to the SOR - because you pass in null-mapped keys for missing entries, as the argument to apply(). So in fact, if your cache/store is empty, and you call

    new HashMap<Number, CharSequence>() {{
      put(3, "three");
      put(2, "two");
      put(1, "one");
    }}.entrySet());

Then, what you will observe is that cacheWriter.writeAll() is called with entries like `{1 => null, 2 => null, 3 => null}`. That's clearly not what you would want to happen. Even worse, if the writer is null, then the store will not be modified at all - because the function returns an empty entry set! Indeed, why should the returned values from the function be different, based on the presence of absence of a writer?

This should all be easy enough to test, though perhaps an integration test is a proper means to do so. One solution would be to simply pass in the arg to putAll() through to writer.writeAll(), and always return the function argument unchanged. The problem with that is you spec'd `bulkCompute()` to support deletions, and OnHeapStore's implementation will actually call through to `writeAll()` with correct null-mapped entries for keys to be removed. The function above though will need to account for that and bifurcate the write and delete operations on the underlying writer, instead of blindly calling `writeAll()`.

Does any of this make sense? I can try and fix this as part of my work on #39 but it feels like it can get hairy quickly...