protected function parseDefinition($definition = null)
    {
        if (is_null($definition)) {
            if (!is_null($this->definition)) {
                throw new \InvalidArgumentException(
                    'Cannot parse rule definitions for rule "'. $this->name. '", attrib "'
                    . $this->attrib->getName(). '" without definition!'
                );
            }
            $definition = $this->definition;
            $this->definition = null;
        }

        // required, simple
        if (is_string($definition) || is_callable($definition)) {
            $definition = array('constraint' => $definition);
        }

        // init empty to reduce isset checks..
        $definition = array_merge(self::$DEFAULT_ATTRIBS, $definition);

        // set attribs
        $this->sufficient = $definition['sufficient'];
        $this->skipEmpty  = $definition['skipEmpty'];
        $this->error      = $definition['error'];

        // having old style callable constraint
        if (is_callable($definition['constraint']) && is_array($definition['constraint'])) { // !($definition['constraint'] instanceof \Closure)) {
            $cb = $definition['constraint'];
            $definition['constraint'] = function () use ($cb) {
                $args = func_get_args();
                return call_user_func_array($cb, $args);
            };
        }

        // from string -> check predefined
        elseif (is_string($definition['constraint'])) {
            $args = preg_split('/:/', $definition['constraint']);
            $method = 'rule'. array_shift($args);
            $found = false;
            foreach ($this->dataFilter->getPredefinedRuleClasses() as $className) {
                if (is_callable(array($className, $method)) && method_exists($className, $method)) {
                    $definition['constraint'] = call_user_func_array(array($className, $method), $args);
                    $found = true;
                    break;
                }
            }
            if (!$found) {
                throw new \InvalidArgumentException(
                    'Could not use constraint "'. $definition['constraint']. '" for rule "'
                    . $this->name. '", attrib "'. $this->attrib->getName(). '" because no '
                    . 'predefined rule class found implementing "'. $method. '()"'
                );
            }
        }

        // determine class
        $constraintClass = is_object($definition['constraint'])
            ? get_class($definition['constraint'])
            : '(Scalar)';

        // at this point: it has to be a closure!
        if ($constraintClass !== 'Closure') {
            throw new \InvalidArgumentException(
                'Definition for rule "'. $this->name. '", attrib "'. $this->attrib->getName(). '"'
                . ' has an invalid constraint of class '. $constraintClass
            );
        }
        $this->constraint = $definition['constraint'];
    }