public function copyBefore(NodeInterface $referenceNode, $nodeName): NodeInterface
    {
        if ($referenceNode->getParent()->getNode($nodeName) !== null) {
            throw new NodeExistsException(sprintf('Node with path "%s/%s" already exists.', $referenceNode->getParent()->getPath(), $nodeName), 1292503465);
        }

        if (!$referenceNode->getParent()->isNodeTypeAllowedAsChildNode($this->getNodeType())) {
            throw new NodeConstraintException(sprintf('Cannot copy %s before %s', $this, $referenceNode), 1402050232);
        }

        $this->emitBeforeNodeCopy($this, $referenceNode->getParent());
        $copiedNode = $this->createRecursiveCopy($referenceNode->getParent(), $nodeName, $this->getNodeType()->isAggregate());
        $copiedNode->moveBefore($referenceNode);

        $this->context->getFirstLevelNodeCache()->flush();
        $this->emitNodeAdded($copiedNode);
        $this->emitAfterNodeCopy($copiedNode, $referenceNode->getParent());

        return $copiedNode;
    }