final public function update(array $keys = null)
    {
        $pre = $this->preUpdate($keys);
        if ($pre === false) {
            $this->logger->error(sprintf(
                'Can not update object "%s:%s"; cancelled by %s::preUpdate()',
                $this->objType(),
                $this->id(),
                get_called_class()
            ));
            return false;
        }

        $ret = $this->source()->updateItem($this, $keys);
        if ($ret === false) {
            $this->logger->error(sprintf(
                'Can not update object "%s:%s"; repository failed for %s',
                $this->objType(),
                $this->id(),
                get_called_class()
            ));
            return false;
        }

        $post = $this->postUpdate($keys);
        if ($post === false) {
            $this->logger->warning(sprintf(
                'Updated object "%s:%s" but %s::postUpdate() failed',
                $this->objType(),
                $this->id(),
                get_called_class()
            ));
            return false;
        }

        return true;
    }