docs: private void store( JcrNodeType nodeType,
                          MutableCachedNode nodeTypes,
                          boolean updateExisting ) {
          assert nodeType != null;
          assert system != null;
          assert nodeTypes != null;
  
          Name name = nodeType.getInternalName();
          final NodeKey key = nodeType.key();
          MutableCachedNode nodeTypeNode = null;
          Set<NodeKey> existingChildKeys = null;
          if (nodeTypes.getChildReferences(system).hasChild(key)) {
              // The node already exists ...
              if (!updateExisting) return;
              nodeTypeNode = system.mutable(key);
  
              // We'll need to delete any existing child that isn't there anymore ...
              existingChildKeys = new HashSet<NodeKey>();
              for (ChildReference childRef : nodeTypeNode.getChildReferences(system)) {
                  existingChildKeys.add(childRef.getKey());
              }
          }
  
          // Define the properties for this node type ...
          NodeType[] supertypes = nodeType.getDeclaredSupertypes();
          List<Name> supertypeNames = new ArrayList<Name>(supertypes.length);
          for (int i = 0; i < supertypes.length; i++) {
              supertypeNames.add(((JcrNodeType)supertypes[i]).getInternalName());
          }
  
          List<Property> properties = new ArrayList<Property>();
          properties.add(propertyFactory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.NODE_TYPE));
          properties.add(propertyFactory.create(JcrLexicon.IS_MIXIN, nodeType.isMixin()));
          properties.add(propertyFactory.create(JcrLexicon.IS_ABSTRACT, nodeType.isAbstract()));
          properties.add(propertyFactory.create(JcrLexicon.IS_QUERYABLE, nodeType.isQueryable()));
  
          if (nodeType.getPrimaryItemName() != null) {
              properties.add(propertyFactory.create(JcrLexicon.PRIMARY_ITEM_NAME, nodeType.getPrimaryItemName()));
          }
  
          properties.add(propertyFactory.create(JcrLexicon.NODE_TYPE_NAME, nodeType.getName()));
          properties.add(propertyFactory.create(JcrLexicon.HAS_ORDERABLE_CHILD_NODES, nodeType.hasOrderableChildNodes()));
          properties.add(propertyFactory.create(JcrLexicon.SUPERTYPES, supertypeNames));
  
          // Now make or adjust the node for the node type ...
          if (nodeTypeNode != null) {
              // Update the properties ...
              nodeTypeNode.setProperties(system, properties);
              // make sure each new supertype of the existing node is present *before* the existing node in the parent nodeTypes
              // this because node type validation is a top-down process, expecting the parents before the children
              for (NodeType superType : supertypes) {
                  CachedNode superTypeNode = system.getNode(((JcrNodeType)superType).key());
                  if (superTypeNode instanceof MutableCachedNode && ((MutableCachedNode)superTypeNode).isNew()) {
                      nodeTypes.reorderChild(system, superTypeNode.getKey(), nodeTypeNode.getKey());
                  }
              }
          } else {
              // We have to create the node type node ...
              nodeTypeNode = nodeTypes.createChild(system, key, name, properties);
          }
  
          // And the property definitions ...
          for (JcrPropertyDefinition defn : nodeType.getDeclaredPropertyDefinitions()) {
              store(nodeTypeNode, defn);
              if (existingChildKeys != null) existingChildKeys.remove(defn.key());
          }
  
          // And the child node definitions ...
          for (JcrNodeDefinition defn : nodeType.getDeclaredChildNodeDefinitions()) {
              store(nodeTypeNode, defn);
              if (existingChildKeys != null) existingChildKeys.remove(defn.key());
          }
  
          // Remove any children that weren't represented by a property definition or child node definition ...
          if (existingChildKeys != null && !existingChildKeys.isEmpty()) {
              for (NodeKey childKey : existingChildKeys) {
                  // Remove the child from the parent, then destrot it ...
                  nodeTypeNode.removeChild(system, childKey);
                  system.destroy(childKey);
              }
          }
      }