public function setSetting( $name, $value )
    {
        $old = isset( $this->settings[$name] )
            ? $this->settings[$name]
            : null;

        if ( $old instanceof self || $value instanceof self )
        {
            if ( $old instanceof self && $value instanceof self )
            {
                $old->setSettings( $value->settings );
            }
            else if ( $old instanceof self )
            {
                if ( $value instanceof Traversable )
                {
                    $value = ArrayUtils::iteratorToArray( $value );
                }

                $old->setSettings( (array) $value );
            }
            else
            {
                $this->settings[$name] = $value;
            }
        }
        else
        {
            $method = array( $this, 'update' . ucfirst( $name ) );

            if ( is_callable( $method ) &&
                 ( ( isset( $value )    && isset( $this->settings[$name] )
                                        && $value != $this->settings[$name] ) ||
                   ( isset( $value )    && ! isset( $this->settings[$name] ) ) ||
                   ( ! isset( $value )  && isset( $this->settings[$name] ) ) ) )
            {
                $value = $method( $value, $old );
            }

            if ( null === $value )
            {
                unset( $this->settings[$name] );
            }
            else
            {
                $this->settings[$name] = $value;
            }
        }

        return $this;
    }