public function add(
        $id,
        $parentId,
        $blockType,
        array $options = [],
        $siblingId = null,
        $prepend = null
    ) {
        $this->validateId($id, true);
        if (isset($this->items[$id])) {
            throw new Exception\ItemAlreadyExistsException(
                sprintf(
                    'The "%s" item already exists.'
                    . ' Remove existing item before add the new item with the same id.',
                    $id
                )
            );
        }
        if (!$parentId && !$this->hierarchy->isEmpty()) {
            throw new Exception\LogicException(
                sprintf(
                    'The "%s" item cannot be the root item'
                    . ' because another root item ("%s") already exists.',
                    $id,
                    $this->hierarchy->getRootId()
                )
            );
        }
        if ($parentId) {
            $parentId = $this->validateAndResolveId($parentId);
        }
        if ($siblingId) {
            $siblingId = $this->resolveId($siblingId);
            if (!isset($this->items[$siblingId])) {
                throw new Exception\ItemNotFoundException(sprintf('The "%s" sibling item does not exist.', $siblingId));
            }
            if ($parentId && $siblingId === $parentId) {
                throw new Exception\LogicException('The sibling item cannot be the same as the parent item.');
            }
        }

        $path = $parentId
            ? $this->getProperty($parentId, self::PATH, true)
            : [];
        $this->hierarchy->add($path, $id, $siblingId, $prepend);
        $path[]           = $id;
        $this->items[$id] = [
            self::PATH       => $path,
            self::BLOCK_TYPE => $blockType,
            self::OPTIONS    => $options
        ];
    }