docs: final AbstractJcrNode addNode( String relPath,
                                     String primaryNodeTypeName,
                                     NodeKey desiredKey,
                                     boolean aclScope )
          throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException,
          RepositoryException {
  
          // Parse the primary type name ...
          Name childPrimaryTypeName = null;
          try {
              childPrimaryTypeName = session.nameFactory().create(primaryNodeTypeName);
          } catch (org.modeshape.jcr.value.ValueFormatException e) {
              throw new RepositoryException(JcrI18n.invalidNodeTypeNameParameter.text(primaryNodeTypeName, "primaryNodeTypeName"));
          }
  
          // Resolve the relative path ...
          Path path = null;
          try {
              path = session.pathFactory().create(relPath);
          } catch (org.modeshape.jcr.value.ValueFormatException e) {
              throw new RepositoryException(JcrI18n.invalidPathParameter.text(relPath, "relPath"));
          }
          if (path.size() == 0 || path.isIdentifier() || path.getLastSegment().getIndex() > 1 || relPath.endsWith("]")) {
              throw new RepositoryException(JcrI18n.invalidPathParameter.text(relPath, "relPath"));
          }
          if (path.size() > 1) {
              // The relative path points to another node, so look for it ...
              Path parentPath = path.getParent();
              try {
                  // Find the parent node ...
                  AbstractJcrItem parent = session.findItem(this, parentPath);
                  if (parent instanceof AbstractJcrNode) {
                      // delegate to the parent node ...
                      Name childName = path.getLastSegment().getName();
                      // MODE-1920: check add_child_node permission on parent node
                      if (!aclScope) {
                          session.checkPermission(absolutePathFor(parent.path(), path.getLastSegment()),
                                                  ModeShapePermissions.ADD_NODE);
                      }
                      return ((AbstractJcrNode)parent).addChildNode(childName, childPrimaryTypeName, desiredKey, false, aclScope);
                  } else if (parent instanceof AbstractJcrProperty) {
                      // Per the TCK, if relPath references a property, then we have to throw a ConstraintViolationException.
                      throw new ConstraintViolationException(JcrI18n.invalidPathParameter.text(relPath, "relPath"));
                  }
              } catch (ItemNotFoundException e) {
                  // We have to convert to a path not found ...
                  throw new PathNotFoundException(e.getMessage(), e.getCause());
              } catch (RepositoryException e) {
                  throw e;
              }
          }
  
          // Otherwise, the path has size == 1 and it specifies the child ...
          if (!aclScope) {
              session.checkPermission(this, ModeShapePermissions.ADD_NODE);
          }
          Name childName = path.getLastSegment().getName();
          return addChildNode(childName, childPrimaryTypeName, desiredKey, false, aclScope);
      }