First stab at caching the hierarchy.
Cache failed lookups.

Also use a derived cache to invalidate the path cache.
We only want to cache PortalPersistentNodes.

This is because PortalNodes hold a reference to a site which may change between requests.
Save a cache miss by making "" and null the same.

A path of "", null and "/" are all the root node.
Add the toString to make debugging easier.
Work correctly with missing sites.
Correctly cache values and null values.

I wasn't caching null values correctly which was causing wrong values to get cached.
Make EPOCH static.

Don't needlessly create objects.
Get rid of static covers.
Cleanup the pom.xml files.

We drop the support for pre-K1 and remove redundant <groupId>s.
Added Javadoc and cleaned up some method signatures.
Cleanup of notes in code.
Give correct reference when generating error.
Do some argument validation on changeSite.
Remove unused getMissingSiteId().

This was part of  getter/setter pair that should never have been.
Add note about the derived cache invalidation.

The derived cache should mean that when a node is no longer cached it's path is no longer cached either. But this may happen due to threading as there isn't any locking across the two caches.
Add some tests for changeSite().
Cleanup JavaDoc.
Our observer isn't all that important.
Comment tidy up.