class AbstractPath implements Path {

    @Override
    public boolean isDescendantOf( Path ancestor ) {
        CheckArg.isNotNull(ancestor, "ancestor");
        if (this == ancestor) return false;
        if (ancestor.isRoot()) return true;
        if (ancestor.size() >= this.size()) return false;

        // Find this path's ancestor that is of the same size ...
        Path thisPath = this.getAncestor(this.size() - ancestor.size());
        Path thatPath = ancestor;
        assert thisPath.size() == thatPath.size();

        // Walk up and compare; it is more likely that the lower path segments differ (plus it's usually more efficient) ...
        while (!thisPath.isRoot() && thisPath.getLastSegment().equals(thatPath.getLastSegment())) {
            thisPath = thisPath.getParent();
            thatPath = thatPath.getParent();
        }
        return thisPath.isRoot();
    }

}