public function mapCriteria(IRowCriteria $criteria) : ILoadCriteria
    {
        $objectCriteria = $this->objectSet instanceof IObjectSetWithLoadCriteriaSupport
            ? $this->objectSet->loadCriteria()
            : new LoadCriteria($this->definition->getClass());

        if ($criteria instanceof IObjectRowCriteria) {
            $objectCriteria = $objectCriteria->merge($criteria->getObjectCriteria());
        }

        foreach ($criteria->getColumnsToLoad() as $column) {
            $objectCriteria->loadAll($this->definition->getPropertiesRequiredFor($column->getName()));
        }

        $mapConditions = function (SpecificationDefinition $objectCriteria, ColumnConditionGroup $conditionGroup) {
            foreach ($conditionGroup->getConditions() as $condition) {
                $objectCriteria->where(
                    $this->mapColumnToPropertyName($condition),
                    $condition->getOperator()->getOperator(),
                    $condition->getValue()
                );
            }
        };

        foreach ($criteria->getConditionGroups() as $columnConditionGroup) {
            if ($columnConditionGroup->getConditionMode() === IRowCriteria::CONDITION_MODE_AND) {
                $mapConditions($objectCriteria, $columnConditionGroup);
            } else {
                $objectCriteria->whereAny(function (SpecificationDefinition $match) use ($mapConditions, $columnConditionGroup) {
                    $mapConditions($match, $columnConditionGroup);
                });
            }
        }

        foreach ($criteria->getOrderings() as $ordering) {
            $objectCriteria->orderBy(
                $this->mapColumnToPropertyName($ordering),
                $ordering->getDirection()
            );
        }

        $objectCriteria->skip($criteria->getRowsToSkip())->limit($criteria->getAmountOfRows());

        return $objectCriteria;
    }