public function setPath($path, $recursive = true)
    {
        if (!is_string($path) || preg_match(NodeInterface::MATCH_PATTERN_PATH, $path) !== 1) {
            throw new \InvalidArgumentException('Invalid path "' . $path . '" (a path must be a valid string, be absolute (starting with a slash) and contain only the allowed characters).', 1284369857);
        }

        if ($path === $this->path) {
            return;
        }

        if ($recursive === true) {
            foreach ($this->getChildNodeData() as $childNodeData) {
                $childNodeData->setPath(NodePaths::addNodePathSegment($path, $childNodeData->getName()));
            }
        }

        $pathBeforeChange = $this->path;

        $this->path = $path;
        $this->calculatePathHash();
        $this->parentPath = NodePaths::getParentPath($path);
        $this->calculateParentPathHash();
        $this->depth = NodePaths::getPathDepth($path);

        if ($pathBeforeChange !== null) {
            // this method is called both for changing the path AND in the constructor of Node; so we only want to do
            // these things below if called OUTSIDE a constructor.
            $this->emitNodePathChanged($this);
            $this->addOrUpdate();
        }
    }