web/views/magicsearch.py
branchtls-sprint
changeset 1433 091ac3ba5d51
parent 1172 959b0e177660
child 1977 606923dff11b
equal deleted inserted replaced
1432:2c3711d4570b 1433:091ac3ba5d51
    39 
    39 
    40     :type translations: dict
    40     :type translations: dict
    41     :param translations: the reverted l10n dict
    41     :param translations: the reverted l10n dict
    42 
    42 
    43     :type schema: `cubicweb.schema.Schema`
    43     :type schema: `cubicweb.schema.Schema`
    44     :param schema: the application's schema    
    44     :param schema: the application's schema
    45     """
    45     """
    46     # var_types is used as a map : var_name / var_type
    46     # var_types is used as a map : var_name / var_type
    47     vartypes = {}
    47     vartypes = {}
    48     # ambiguous_nodes is used as a map : relation_node / (var_name, available_translations)
    48     # ambiguous_nodes is used as a map : relation_node / (var_name, available_translations)
    49     ambiguous_nodes = {}
    49     ambiguous_nodes = {}
   105         eschema = schema.eschema(vartype)
   105         eschema = schema.eschema(vartype)
   106         rtype = _get_approriate_translation(translations_found, eschema)
   106         rtype = _get_approriate_translation(translations_found, eschema)
   107         if rtype is None:
   107         if rtype is None:
   108             continue
   108             continue
   109         relation.r_type = rtype
   109         relation.r_type = rtype
   110     
   110 
   111 
   111 
   112 
   112 
   113 QUOTED_SRE = re.compile(r'(.*?)(["\'])(.+?)\2')
   113 QUOTED_SRE = re.compile(r'(.*?)(["\'])(.+?)\2')
   114 
   114 
   115 TRANSLATION_MAPS = {}
   115 TRANSLATION_MAPS = {}
   143         args = self.preprocess_query(uquery, req)
   143         args = self.preprocess_query(uquery, req)
   144         try:
   144         try:
   145             return req.execute(*args)
   145             return req.execute(*args)
   146         finally:
   146         finally:
   147             # rollback necessary to avoid leaving the connection in a bad state
   147             # rollback necessary to avoid leaving the connection in a bad state
   148             req.cnx.rollback() 
   148             req.cnx.rollback()
   149 
   149 
   150     def preprocess_query(self, uquery, req):
   150     def preprocess_query(self, uquery, req):
   151         raise NotImplementedError()
   151         raise NotImplementedError()
   152 
   152 
   153 
   153 
   159     """
   159     """
   160     name = 'rql'
   160     name = 'rql'
   161     priority = 0
   161     priority = 0
   162     def preprocess_query(self, uquery, req):
   162     def preprocess_query(self, uquery, req):
   163         return uquery,
   163         return uquery,
   164     
   164 
   165 
   165 
   166 class QueryTranslator(BaseQueryProcessor):
   166 class QueryTranslator(BaseQueryProcessor):
   167     """ parses through rql and translates into schema language entity names 
   167     """ parses through rql and translates into schema language entity names
   168     and attributes
   168     and attributes
   169     """
   169     """
   170     priority = 2
   170     priority = 2
   171     def preprocess_query(self, uquery, req):
   171     def preprocess_query(self, uquery, req):
   172         try:
   172         try:
   183     """Quick search preprocessor
   183     """Quick search preprocessor
   184 
   184 
   185     preprocessing query in shortcut form to their RQL form
   185     preprocessing query in shortcut form to their RQL form
   186     """
   186     """
   187     priority = 4
   187     priority = 4
   188     
   188 
   189     def preprocess_query(self, uquery, req):
   189     def preprocess_query(self, uquery, req):
   190         """try to get rql from an unicode query string"""
   190         """try to get rql from an unicode query string"""
   191         args = None
   191         args = None
   192         self.req = req
   192         self.req = req
   193         try:
   193         try:
   194             # Process as if there was a quoted part
   194             # Process as if there was a quoted part
   195             args = self._quoted_words_query(uquery)
   195             args = self._quoted_words_query(uquery)
   196         ## No quoted part  
   196         ## No quoted part
   197         except BadRQLQuery:
   197         except BadRQLQuery:
   198             words = uquery.split()
   198             words = uquery.split()
   199             if len(words) == 1:
   199             if len(words) == 1:
   200                 args = self._one_word_query(*words)
   200                 args = self._one_word_query(*words)
   201             elif len(words) == 2:
   201             elif len(words) == 2:
   203             elif len(words) == 3:
   203             elif len(words) == 3:
   204                 args = self._three_words_query(*words)
   204                 args = self._three_words_query(*words)
   205             else:
   205             else:
   206                 args = self._multiple_words_query(words)
   206                 args = self._multiple_words_query(words)
   207         return args
   207         return args
   208     
   208 
   209     def _get_entity_type(self, word):
   209     def _get_entity_type(self, word):
   210         """check if the given word is matching an entity type, return it if
   210         """check if the given word is matching an entity type, return it if
   211         it's the case or raise BadRQLQuery if not
   211         it's the case or raise BadRQLQuery if not
   212         """
   212         """
   213         etype = word.capitalize()
   213         etype = word.capitalize()
   214         try:
   214         try:
   215             return trmap(self.config, self.vreg.schema, self.req.lang)[etype]
   215             return trmap(self.config, self.vreg.schema, self.req.lang)[etype]
   216         except KeyError:
   216         except KeyError:
   217             raise BadRQLQuery('%s is not a valid entity name' % etype)        
   217             raise BadRQLQuery('%s is not a valid entity name' % etype)
   218 
   218 
   219     def _get_attribute_name(self, word, eschema):
   219     def _get_attribute_name(self, word, eschema):
   220         """check if the given word is matching an attribute of the given entity type,
   220         """check if the given word is matching an attribute of the given entity type,
   221         return it normalized if found or return it untransformed else
   221         return it normalized if found or return it untransformed else
   222         """
   222         """
   259                 searchop = 'LIKE '
   259                 searchop = 'LIKE '
   260         searchattr = searchattr or 'has_text'
   260         searchattr = searchattr or 'has_text'
   261         if var is None:
   261         if var is None:
   262             var = etype[0]
   262             var = etype[0]
   263         return '%s %s %s%%(text)s' % (var, searchattr, searchop)
   263         return '%s %s %s%%(text)s' % (var, searchattr, searchop)
   264         
   264 
   265     def _two_words_query(self, word1, word2):
   265     def _two_words_query(self, word1, word2):
   266         """Specific process for two words query (case (2) of preprocess_rql)
   266         """Specific process for two words query (case (2) of preprocess_rql)
   267         """
   267         """
   268         etype = self._get_entity_type(word1)
   268         etype = self._get_entity_type(word1)
   269         # this is a valid RQL query : ("Person X", or "Person TMP1")
   269         # this is a valid RQL query : ("Person X", or "Person TMP1")
   270         if len(word2) == 1 and word2.isupper():
   270         if len(word2) == 1 and word2.isupper():
   271             return '%s %s' % (etype, word2),
   271             return '%s %s' % (etype, word2),
   272         # else, suppose it's a shortcut like : Person Smith
   272         # else, suppose it's a shortcut like : Person Smith
   273         rql = '%s %s WHERE %s' % (etype, etype[0], self._complete_rql(word2, etype))
   273         rql = '%s %s WHERE %s' % (etype, etype[0], self._complete_rql(word2, etype))
   274         return rql, {'text': word2}
   274         return rql, {'text': word2}
   275            
   275 
   276     def _three_words_query(self, word1, word2, word3):
   276     def _three_words_query(self, word1, word2, word3):
   277         """Specific process for three words query (case (3) of preprocess_rql)
   277         """Specific process for three words query (case (3) of preprocess_rql)
   278         """
   278         """
   279         etype = self._get_entity_type(word1)
   279         etype = self._get_entity_type(word1)
   280         eschema = self.schema.eschema(etype)
   280         eschema = self.schema.eschema(etype)
   334         elif len(left_words) == 2:
   334         elif len(left_words) == 2:
   335             word1, word2 = left_words
   335             word1, word2 = left_words
   336             return self._three_words_query(word1, word2, quoted_part)
   336             return self._three_words_query(word1, word2, quoted_part)
   337             # return ori_rql
   337             # return ori_rql
   338         raise BadRQLQuery("unable to handle request %r" % ori_rql)
   338         raise BadRQLQuery("unable to handle request %r" % ori_rql)
   339     
   339 
   340 
   340 
   341  
   341 
   342 class FullTextTranslator(BaseQueryProcessor):
   342 class FullTextTranslator(BaseQueryProcessor):
   343     priority = 10
   343     priority = 10
   344     name = 'text'
   344     name = 'text'
   345     
   345 
   346     def preprocess_query(self, uquery, req):
   346     def preprocess_query(self, uquery, req):
   347         """suppose it's a plain text query"""
   347         """suppose it's a plain text query"""
   348         return 'Any X WHERE X has_text %(text)s', {'text': uquery}
   348         return 'Any X WHERE X has_text %(text)s', {'text': uquery}
   349 
   349 
   350 
   350