docs: protected NodeCacheIterator nodes( String workspaceName,
                                         Path path ) {
          // Determine which filter we should use based upon the workspace name. For the system workspace,
          // all queryable nodes are included. For all other workspaces, all queryable nodes are included except
          // for those that are actually stored in the system workspace (e.g., the "/jcr:system" nodes).
          NodeFilter nodeFilterForWorkspace = nodeFilterForWorkspace(workspaceName);
          if (nodeFilterForWorkspace == null) return null;
          // always append a shared nodes filter to the end of the workspace filter,
          // JCR #14.16 -If a query matches a descendant node of a shared set, it appears in query results only once.
          NodeFilter compositeFilter = new CompositeNodeFilter(nodeFilterForWorkspace, sharedNodesFilter());
  
          // Then create an iterator over that workspace ...
          NodeCache cache = repo.getWorkspaceCache(workspaceName);
          NodeKey startingNode = null;
          if (path != null) {
              CachedNode node = getNodeAtPath(path, cache);
              if (node != null) startingNode = node.getKey();
          } else {
              startingNode = cache.getRootKey();
          }
          if (startingNode != null) {
              return new NodeCacheIterator(cache, startingNode, compositeFilter);
          }
          return null;
      }