public function save(EntityInterface $resource, $options = [])
    {
        $options = new ArrayObject((array)$options + [
                'checkRules' => true,
                'checkExisting' => false,
            ]);

        if ($resource->getErrors()) {
            return false;
        }

        if ($resource->isNew() === false && !$resource->isDirty()) {
            return $resource;
        }

        $primaryColumns = (array)$this->getPrimaryKey();

        if ($options['checkExisting'] && $primaryColumns && $resource->isNew() && $resource->has($primaryColumns)) {
            $alias = $this->getAlias();
            $conditions = [];
            foreach ($resource->extract($primaryColumns) as $k => $v) {
                $conditions["$alias.$k"] = $v;
            }
            $resource->isNew(!$this->exists($conditions));
        }

        $mode = $resource->isNew() ? RulesChecker::CREATE : RulesChecker::UPDATE;
        if ($options['checkRules'] && !$this->checkRules($resource, $mode, $options)) {
            return false;
        }

        $event = $this->dispatchEvent('Model.beforeSave', compact('resource', 'options'));

        if ($event->isStopped()) {
            return $event->result;
        }

        $data = $resource->extract($this->getSchema()->columns(), true);

        if ($resource->isNew()) {
            $query = $this->query()->create();
        } else {
            $query = $this->query()->update()->where($resource->extract($primaryColumns));
        }
        $query->set($data);

        $result = $query->execute();
        if (!$result) {
            return false;
        }

        if (($resource->isNew()) && ($result instanceof EntityInterface)) {
            return $result;
        }

        $className = get_class($resource);

        return new $className($resource->toArray(), [
            'markNew' => false,
            'markClean' => true
        ]);
    }