public function end($setter = null)
    {
        if (!count($this->stack)) {
            throw new \UnexpectedValueException("Stack is empty. Did you call end() too many times?");
        }
        $current = array_pop($this->stack);
        if ($parent = $this->current()) {
            $parentClassName = get_class($parent);
            $entityLocalName = Str::classname(get_class($current));

            if ($current instanceof $parentClassName) {
                if (method_exists($parent, 'addChildren')) {
                    call_user_func(array($parent, 'addChildren'), $current);
                }
            }
            if (is_null($setter)) {
                foreach (array('set', 'add') as $methodPrefix) {
                    $methodName = $methodPrefix . $entityLocalName;

                    if (method_exists($parent, $methodName)) {
                        $setter = $methodName;
                        break;
                    }
                }
            }
            if (!is_null($setter)) {
                call_user_func(array($parent, $setter), $current);
            }

            $parentClassNames = array_merge(class_parents($parentClassName), array($parentClassName));

            foreach (array_reverse($parentClassNames) as $lParentClassName) {
                $lParentClass = Str::classname($lParentClassName);
                $parentSetter = 'set' . $lParentClass;
                if ($lParentClassName == get_class($current)) {
                    $parentSetter = 'setParent';
                }
                if (method_exists($current, $parentSetter)) {
                    call_user_func(
                        array($current, $parentSetter),
                        $parent
                    );
                    break;
                }
            }
            foreach ($this->alwaysDo as $callable) {
                call_user_func($callable, $parent);
            }
        }
        foreach ($this->alwaysDo as $callable) {
            call_user_func($callable, $current);
        }
        return $this;
    }