protected function validate()
    {
        if (!empty($this->errors)) {
            // already validated
            return;
        }

        $this->errors = [];

        foreach ($this->rules as $field => $rules) {

            $value = $this->getValue($field);

            foreach ($this->provider->getRules($rules) as $rule) {
                if ($rule->ignoreEmpty($value) && empty($rule->hasConditions())) {
                    continue;
                }

                foreach ($rule->getConditions() as $condition) {
                    if (!$condition->isMet($this, $field, $value)) {
                        // condition is not met, skipping validation
                        continue 2;
                    }
                }

                if (!$rule->validate($this, $field, $value)) {
                    // got error, jump to next field
                    $this->errors[$field] = $rule->getMessage($field, $value);
                    break;
                }
            }
        }
    }