docs: void unregisterNodeType( Collection<Name> nodeTypeNames,
                               boolean failIfNodeTypesAreUsed )
          throws NoSuchNodeTypeException, InvalidNodeTypeDefinitionException, RepositoryException {
          CheckArg.isNotNull(nodeTypeNames, "nodeTypeNames");
          if (nodeTypeNames.isEmpty()) return;
  
          if (failIfNodeTypesAreUsed) {
              long start = System.nanoTime();
              // Search the content graph to make sure that this type isn't being used
              for (Name nodeTypeName : nodeTypeNames) {
                  if (isNodeTypeInUse(nodeTypeName)) {
                      String name = nodeTypeName.getString(context.getNamespaceRegistry());
                      throw new InvalidNodeTypeDefinitionException(JcrI18n.cannotUnregisterInUseType.text(name));
                  }
              }
              long time = TimeUnit.MILLISECONDS.convert(Math.abs(System.nanoTime() - start), TimeUnit.NANOSECONDS);
              logger.debug("{0} milliseconds to check if any of these node types are unused before unregistering them: {1}", time,
                           nodeTypeNames);
          }
  
          try {
              /*
               * Grab an exclusive lock on this data to keep other nodes from being added/saved while the unregistration checks are occurring
               */
              List<JcrNodeType> removedNodeTypes = new ArrayList<JcrNodeType>(nodeTypeNames.size());
              nodeTypesLock.writeLock().lock();
              final NodeTypes nodeTypes = this.nodeTypesCache;
  
              for (Name nodeTypeName : nodeTypeNames) {
                  /*
                   * Check that the type names are valid
                   */
                  if (nodeTypeName == null) {
                      throw new NoSuchNodeTypeException(JcrI18n.invalidNodeTypeName.text());
                  }
                  String name = nodeTypeName.getString(context.getNamespaceRegistry());
  
                  JcrNodeType foundNodeType = nodeTypes.getNodeType(nodeTypeName);
                  if (foundNodeType == null) {
                      throw new NoSuchNodeTypeException(JcrI18n.noSuchNodeType.text(name));
                  }
                  removedNodeTypes.add(foundNodeType);
  
                  /*
                   * Check that no other node definitions have dependencies on any of the named types
                   */
                  for (JcrNodeType nodeType : nodeTypes.getAllNodeTypes()) {
                      // If this node is also being unregistered, don't run checks against it
                      if (nodeTypeNames.contains(nodeType.getInternalName())) {
                          continue;
                      }
  
                      for (JcrNodeType supertype : nodeType.supertypes()) {
                          if (nodeTypeName.equals(supertype.getInternalName())) {
                              throw new InvalidNodeTypeDefinitionException(JcrI18n.cannotUnregisterSupertype.text(name,
                                                                                                                  nodeType.getName()));
                          }
                      }
  
                      for (JcrNodeDefinition childNode : nodeType.childNodeDefinitions()) {
                          NodeType defaultPrimaryType = childNode.getDefaultPrimaryType();
                          if (defaultPrimaryType != null && name.equals(defaultPrimaryType.getName())) {
                              throw new InvalidNodeTypeDefinitionException(
                                                                           JcrI18n.cannotUnregisterDefaultPrimaryType.text(name,
                                                                                                                           nodeType.getName(),
                                                                                                                           childNode.getName()));
                          }
                          if (childNode.requiredPrimaryTypeNameSet().contains(nodeTypeName)) {
                              throw new InvalidNodeTypeDefinitionException(
                                                                           JcrI18n.cannotUnregisterRequiredPrimaryType.text(name,
                                                                                                                            nodeType.getName(),
                                                                                                                            childNode.getName()));
                          }
                      }
                  }
              }
  
              // Create the new cache ...
              NodeTypes newNodeTypes = nodeTypes.without(removedNodeTypes);
  
              // Remove the node types from persistent storage ...
              SessionCache system = repository.createSystemSession(context, false);
              SystemContent systemContent = new SystemContent(system);
              systemContent.unregisterNodeTypes(removedNodeTypes.toArray(new JcrNodeType[removedNodeTypes.size()]));
              systemContent.save();
  
              // Now change the cache ...
              this.nodeTypesCache = newNodeTypes;
              this.schemata = null;
              notifiyListeners();
          } finally {
              nodeTypesLock.writeLock().unlock();
          }
      }