Perform a smart search on VRF list.

            * `auth` [BaseAuth]
                AAA options.
            * `query_str` [string]
                Search string
            * `search_options` [options_dict]
                Search options. See :func:`search_vrf`.
            * `extra_query` [dict_to_sql]
                Extra search terms, will be AND:ed together with what is
                extracted from the query string.

            Return a dict with three elements:
                * :attr:`interpretation` - How the query string was interpreted.
                * :attr:`search_options` - Various search_options.
                * :attr:`result` - The search result.

                The :attr:`interpretation` is given as a list of dicts, each
                explaining how a part of the search key was interpreted (ie. what
                VRF attribute the search operation was performed on).

                The :attr:`result` is a list of dicts containing the search result.

            The smart search function tries to convert the query from a text
            string to a `query` dict which is passed to the
            :func:`search_vrf` function.  If multiple search keys are
            detected, they are combined with a logical AND.

            It will basically just take each search term and try to match it
            against the name or description column with regex match or the VRF
            column with an exact match.

            See the :func:`search_vrf` function for an explanation of the
            `search_options` argument.

            This is the documentation of the internal backend function. It's
            exposed over XML-RPC, please also see the XML-RPC documentation for
            :py:func:`nipap.xmlrpc.NipapXMLRPC.smart_search_vrf` for full
            understanding.

def smart_search_vrf(self, auth, query_str, search_options=None, extra_query=None):
        """ Perform a smart search on VRF list.

            * `auth` [BaseAuth]
                AAA options.
            * `query_str` [string]
                Search string
            * `search_options` [options_dict]
                Search options. See :func:`search_vrf`.
            * `extra_query` [dict_to_sql]
                Extra search terms, will be AND:ed together with what is
                extracted from the query string.

            Return a dict with three elements:
                * :attr:`interpretation` - How the query string was interpreted.
                * :attr:`search_options` - Various search_options.
                * :attr:`result` - The search result.

                The :attr:`interpretation` is given as a list of dicts, each
                explaining how a part of the search key was interpreted (ie. what
                VRF attribute the search operation was performed on).

                The :attr:`result` is a list of dicts containing the search result.

            The smart search function tries to convert the query from a text
            string to a `query` dict which is passed to the
            :func:`search_vrf` function.  If multiple search keys are
            detected, they are combined with a logical AND.

            It will basically just take each search term and try to match it
            against the name or description column with regex match or the VRF
            column with an exact match.

            See the :func:`search_vrf` function for an explanation of the
            `search_options` argument.

            This is the documentation of the internal backend function. It's
            exposed over XML-RPC, please also see the XML-RPC documentation for
            :py:func:`nipap.xmlrpc.NipapXMLRPC.smart_search_vrf` for full
            understanding.
        """

        if search_options is None:
            search_options = {}

        self._logger.debug("smart_search_vrf query string: %s" % query_str)

        success, query = self._parse_vrf_query(query_str)
        if not success:
            return {
                'interpretation': query,
                'search_options': search_options,
                'result': [],
                'error': True,
                'error_message': 'query interpretation failed'
            }

        if extra_query is not None:
            query = {
                'operator': 'and',
                'val1': query,
                'val2': extra_query
            }

        self._logger.debug("smart_search_vrf; query expanded to: %s" % unicode(query))

        search_result = self.search_vrf(auth, query, search_options)
        search_result['interpretation'] = query
        search_result['error'] = False

        return search_result