docs: public MutableCachedNode recordNewVersion( CachedNode versionableNode,
                                                 SessionCache cacheForVersionableNode,
                                                 Path versionHistoryPath,
                                                 NodeKey originalVersionKey,
                                                 Collection<Property> versionableProperties,
                                                 DateTime now,
                                                 AtomicReference<MutableCachedNode> frozenNodeOutput ) {
          assert versionHistoryPath != null;
          assert versionHistoryPath.size() == 6;
  
          // Get the information from this node ...
          NodeKey versionableNodeKey = versionableNode.getKey();
          Name primaryTypeName = versionableNode.getPrimaryType(cacheForVersionableNode);
          Set<Name> mixinTypeNames = versionableNode.getMixinTypes(cacheForVersionableNode);
          NodeKey versionHistoryKey = versionHistoryNodeKeyFor(versionableNodeKey);
  
          // Find the existing version history for this node (if it exists) ...
          Name versionName = null;
          MutableCachedNode historyNode = system.mutable(versionHistoryKey);
          Property predecessors = null;
          NodeKey versionKey = versionHistoryKey.withRandomId();
          if (historyNode == null) {
              // Initialize the version history ...
              historyNode = initializeVersionStorage(versionableNodeKey, versionHistoryKey, null, primaryTypeName, mixinTypeNames,
                                                     versionHistoryPath, originalVersionKey, now);
              // Overwrite the predecessor's property ...
              NodeKey rootVersionKey = historyNode.getChildReferences(system).getChild(JcrLexicon.ROOT_VERSION).getKey();
              Reference rootVersionRef = referenceFactory.create(rootVersionKey, true);
              predecessors = propertyFactory.create(JcrLexicon.PREDECESSORS, new Object[] {rootVersionRef});
              versionName = names.create("1.0");
          } else {
              ChildReferences historyChildren = historyNode.getChildReferences(system);
              predecessors = versionableNode.getProperty(JcrLexicon.PREDECESSORS, cacheForVersionableNode);
              versionName = nextNameForVersionNode(predecessors, historyChildren);
          }
  
          // Create a 'nt:version' node under the version history node ...
          List<Property> props = new ArrayList<Property>();
          props.add(propertyFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.VERSION));
          props.add(predecessors);
          props.add(propertyFactory.create(JcrLexicon.CREATED, now));
          props.add(propertyFactory.create(JcrLexicon.UUID, versionKey.getIdentifier()));
          MutableCachedNode versionNode = historyNode.createChild(system, versionKey, versionName, props);
  
          // Create a 'nt:frozenNode' node under the 'nt:version' node ...
          NodeKey frozenNodeKey = systemKey().withRandomId();
  
          props = new ArrayList<Property>();
          props.add(propertyFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FROZEN_NODE));
          props.add(propertyFactory.create(JcrLexicon.FROZEN_UUID, versionableNodeKey.getIdentifier()));
          props.add(propertyFactory.create(JcrLexicon.FROZEN_PRIMARY_TYPE, primaryTypeName));
          props.add(propertyFactory.create(JcrLexicon.FROZEN_MIXIN_TYPES, mixinTypeNames));
          props.add(propertyFactory.create(JcrLexicon.UUID, frozenNodeKey));
  
          if (versionableProperties != null) props.addAll(versionableProperties);
          MutableCachedNode frozenNode = versionNode.createChild(system, frozenNodeKey, JcrLexicon.FROZEN_NODE, props);
          assert frozenNode != null;
          frozenNodeOutput.set(frozenNode);
  
          // Now update the predecessor nodes to have the new version node be included as one of their successors ...
          Property successors = null;
          final Set<Reference> successorReferences = new HashSet<Reference>();
          for (Object value : predecessors) {
              NodeKey predecessorKey = ((NodeKeyReference)value).getNodeKey();
              CachedNode predecessor = system.getNode(predecessorKey);
  
              // Look up the 'jcr:successors' property on the predecessor ...
              successors = predecessor.getProperty(JcrLexicon.SUCCESSORS, system);
              if (successors != null) {
                  // There were already successors, so we need to add our new version node the list ...
                  successorReferences.clear();
                  for (Object successorValue : successors) {
                      NodeKey successorKey = ((NodeKeyReference)successorValue).getNodeKey();
                      successorReferences.add(referenceFactory.create(successorKey, true));
                  }
              }
  
              // Now add the uuid of the versionable node ...
              successorReferences.add(referenceFactory.create(versionKey, true));
  
              successors = propertyFactory.create(JcrLexicon.SUCCESSORS, org.modeshape.jcr.value.PropertyType.REFERENCE,
                                                  successorReferences);
              system.mutable(predecessorKey).setProperty(system, successors);
          }
  
          // Return the newly-created version node ...
          return versionNode;
      }