[CalendarServer-changes] [9158] CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav /directory/opendirectorybacker.py

source_changes at macosforge.org source_changes at macosforge.org
Thu Apr 19 17:33:24 PDT 2012


Revision: 9158
          http://trac.macosforge.org/projects/calendarserver/changeset/9158
Author:   gaya at apple.com
Date:     2012-04-19 17:33:24 -0700 (Thu, 19 Apr 2012)
Log Message:
-----------
fix and simplify dsFilterFromAddressBookFilter()

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py	2012-04-20 00:32:26 UTC (rev 9157)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py	2012-04-20 00:33:24 UTC (rev 9158)
@@ -193,17 +193,6 @@
         self.vcardPropToSearchableDSAttrMap = vcardPropToSearchableDSAttrMap
         self.log_debug("self.vcardPropToSearchableDSAttrMap=%s" % (self.vcardPropToSearchableDSAttrMap, ))
  
-        # calculate unsearch map - a map of the binary attributes.  
-        vCardPropToUnsearchableDSAttrMap = {}
-        for prop, dsAttributeList in ABDirectoryQueryResult.vcardPropToDSAttrMap.iteritems():
-            for attr in dsAttributeList:
-                if isinstance(attr, tuple):
-                    vCardPropToUnsearchableDSAttrMap[prop] = dsAttributeList
-                    
-        self.vCardPropToUnsearchableDSAttrMap = vCardPropToUnsearchableDSAttrMap
-        self.log_debug("self.vCardPropToUnsearchableDSAttrMap=%s" % (self.vCardPropToUnsearchableDSAttrMap, ))
-        
-        
         #get attributes required for needed for valid vCard
         requiredAttributes = [attr for prop in ("UID", "FN", "N") for attr in ABDirectoryQueryResult.vcardPropToDSAttrMap[prop]]
         requiredAttributes += [dsattributes.kDS1AttrModificationTimestamp, dsattributes.kDS1AttrCreationTimestamp,] # for VCardResult DAVPropertyMixIn
@@ -487,13 +476,13 @@
             return self.returnedAttributes
         
         else:
-            queryAttributes = self.requiredAttributes
+            queryAttributes = []
             for prop in propertyNames:
-                attributes = self.vcardPropToSearchableDSAttrMap.get(prop)
+                attributes = ABDirectoryQueryResult.vcardPropToDSAttrMap(prop)
                 if attributes:
                     queryAttributes += attributes
                     
-            return list(set(queryAttributes))
+            return list(set(queryAttributes + self.requiredAttributes).intersection(self.returnedAttributes))
 
     
 
@@ -503,7 +492,9 @@
         Get vCards for a given addressBookFilter and addressBookQuery
         """
     
-        allRecords, filterAttributes, dsFilter  = dsFilterFromAddressBookFilter( addressBookFilter, self.vcardPropToSearchableDSAttrMap,
+        allRecords, filterAttributes, dsFilter  = dsFilterFromAddressBookFilter( addressBookFilter, 
+                                                                                 self.vcardPropToSearchableDSAttrMap,
+                                                                                 ABDirectoryQueryResult.vcardPropToDSAttrMap,
                                                                                  constantProperties=ABDirectoryQueryResult.constantProperties );
         self.log_debug("allRecords = %s, query = %s" % (allRecords, "None" if dsFilter is None else dsFilter.generate(),))
 
@@ -606,21 +597,17 @@
     return (etagRequested, propertyNames if len(propertyNames) else None)
 
 
-def dsFilterFromAddressBookFilter(addressBookFilter, vcardPropToSearchableAttrMap, vcardPropToUnsearchableAttrMap={}, constantProperties={}):
+def dsFilterFromAddressBookFilter(addressBookFilter, vcardPropToSearchableAttrMap, vcardPropToAttrMap={}, constantProperties={}):
     """
     Convert the supplied addressbook-query into a ds expression tree.
 
     @param addressBookFilter: the L{Filter} for the addressbook-query to convert.
-    @param vcardPropToSearchableAttrMap: a mapping from vcard properties to query attributes.
-    @param vcardPropToUnsearchableAttrMap: a mapping from vcard properties to unsearchable query attributes. (unused)
+    @param vcardPropToSearchableAttrMap: a mapping from vcard properties to searchable query attributes.
+    @param vcardPropToAttrMap: a mapping from vcard properties to all query attributes. Need for correct expressionAttributes below
     @param constantProperties: a mapping of constant properties.  A query on a constant property will return all or None
     @return: (needsAllRecords, expressionAttributes, expression) tuple
     """
-    #TODO:  1. get rid of needsAllRecords: instead should be: expression==None means list all results, expression==False means no results
-    #       2. expressionAttributes returned is incorrect in many cases: e.g. "return (xxx, [], [])" below
-    #            but needs a full mapping. Perhaps this call should return a propFilter.filter_name list instead 
-    #       3. vcardPropToUnsearchableAttrMap is unused by callers. In the past, vcardPropToUnsearchableAttrMap was that part of vCardProp map
-    #            containing binary attributes.  Current behavior is that properties not in vcardPropToSearchableAttrMap are ignored.
+    #TODO:  get rid of needsAllRecords: instead should be: expression==None means list all results, expression==False means no results
     #
     def propFilterListQuery(filterAllOf, propFilters):
 
@@ -633,29 +620,29 @@
             @return: (needsAllRecords, expressionAttributes, expressions) tuple
             """
             
-            def definedExpression( defined, allOf, filterName, constant, queryAttributes, allAttrNames):
-                if constant or filterName in ("N" , "FN", "UID", "SOURCE",):
-                    return (defined, [], [])     # all records have this property so no records do not have it
+            def definedExpression( defined, allOf ):
+                if constant or propFilter.filter_name in ("N" , "FN", "UID", "SOURCE",):
+                    return (defined, propFilterAttrNames, [])     # all records have this property so no records do not have it
                 else:
-                    matchList = [dsquery.match(attrName, "", dsattributes.eDSStartsWith) for attrName in allAttrNames]
+                    matchList = [dsquery.match(attrName, "", dsattributes.eDSStartsWith) for attrName in searchablePropFilterAttrNames]
                     if defined:
-                        return andOrExpression(allOf, queryAttributes, matchList)
+                        return andOrExpression(allOf, matchList)
                     else:
                         if len(matchList) > 1:
                             expr = dsquery.expression( dsquery.expression.OR, matchList )
                         else:
                             expr = matchList[0]
-                        return (False, queryAttributes, [dsquery.expression( dsquery.expression.NOT, expr),])
+                        return (False, propFilterAttrNames, [dsquery.expression( dsquery.expression.NOT, expr),])
                 #end definedExpression()
 
 
-            def andOrExpression(propFilterAllOf, queryAttributes, matchList):
-                #print("andOrExpression(propFilterAllOf=%r, queryAttributes%r, matchList%r)" % (propFilterAllOf, queryAttributes, matchList))
+            def andOrExpression(propFilterAllOf, matchList):
+                #print("andOrExpression(propFilterAllOf=%r, propFilterAttrNames%r, matchList%r)" % (propFilterAllOf, propFilterAttrNames, matchList))
                 if propFilterAllOf and len(matchList) > 1:
                     # add OR expression because parent will AND
-                    return (False, queryAttributes, [dsquery.expression( dsquery.expression.OR, matchList),])
+                    return (False, propFilterAttrNames, [dsquery.expression( dsquery.expression.OR, matchList),])
                 else:
-                    return (False, queryAttributes, matchList)
+                    return (False, propFilterAttrNames, matchList)
                 #end andOrExpression()
                 
 
@@ -753,15 +740,15 @@
                 if constant:
                     # do the match right now!  Return either all or none.
                     #FIXME: match is not implemented in twisteddaldav.query.addressbookqueryfilter.TextMatch so use _match for now
-                    return( textMatchElement._match([constant,]), [], [] )
+                    return( textMatchElement._match([constant,]), propFilterAttrNames, [] )
                 else:
 
                     matchStrings = getMatchStrings(propFilter, textMatchElement.text)
 
-                    if not len(matchStrings) or unsearchableAttributes:
+                    if not len(matchStrings):
                         # no searching text in binary ds attributes, so change to defined/not defined case
                         if textMatchElement.negate:
-                            return definedExpression(False, propFilterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrNames)
+                            return definedExpression(False, propFilterAllOf)
                         # else fall through to attribute exists case below
                     else:
                         
@@ -779,11 +766,11 @@
                                         log.debug("Could not decode UID string %r in %r: %r" % (matchString[recordNameStart:], matchString, e,))
                                     else:
                                         if textMatchElement.negate:
-                                            return (False, queryAttributes, 
+                                            return (False, propFilterAttrNames, 
                                                     [dsquery.expression(dsquery.expression.NOT, dsquery.match(dsattributes.kDSNAttrRecordName, recordNameQualifier, dsattributes.eDSExact)),]
                                                     )
                                         else:
-                                            return (False, queryAttributes, 
+                                            return (False, propFilterAttrNames, 
                                                     [dsquery.match(dsattributes.kDSNAttrRecordName, recordNameQualifier, dsattributes.eDSExact),]
                                                     )
                         
@@ -809,42 +796,41 @@
                                 expr = dsquery.expression( dsquery.expression.OR, matchList )
                             else:
                                 expr = matchList[0]
-                            return (False, queryAttributes, [dsquery.expression( dsquery.expression.NOT, expr),])
+                            return (False, propFilterAttrNames, [dsquery.expression( dsquery.expression.NOT, expr),])
                         else:
-                            return andOrExpression(propFilterAllOf, queryAttributes, matchList)
+                            return andOrExpression(propFilterAllOf, matchList)
 
                 # attribute exists search
-                return definedExpression(True, propFilterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrNames)
+                return definedExpression(True, propFilterAllOf)
                 #end textMatchElementExpression()
                 
 
-            # queryAttributes are attributes used by this query needed for building vCard and correct post-filtering
+            # propFilterAttrNames are attributes to be used by this propfilter's expression
             searchableAttributes = vcardPropToSearchableAttrMap.get(propFilter.filter_name, [])
             if isinstance(searchableAttributes, str):
                 searchableAttributes = [searchableAttributes,]
-                
-            unsearchableAttributes = vcardPropToUnsearchableAttrMap.get(propFilter.filter_name, [])
-            if isinstance(unsearchableAttributes, str):
-                unsearchableAttributes = [unsearchableAttributes,]
+            searchablePropFilterAttrNames = list(searchableAttributes)
             
-            #log.debug("searchableAttributes=%s" % (searchableAttributes,))
-            #log.debug("unsearchableAttributes=%s" % (unsearchableAttributes,))
-            queryAttributes = list(searchableAttributes) + list(unsearchableAttributes)
-            if not queryAttributes:
-                # not allAttrNames means propFilter.filter_name is not mapped
-                # return None to try to match all items if this is the only property filter
-                return (None, [], [])
-            
-            allAttrNames = []
-            for attrName in queryAttributes:
+            # propFilterAttributes is full list of all attributes need to be returned from a future query to support post-filters for propfilter
+            propFilterAttributes = vcardPropToAttrMap.get(propFilter.filter_name, [])
+            if isinstance(propFilterAttributes, str):
+                searchableAttributes = [propFilterAttributes,]
+            propFilterAttrNames = []
+            for attrName in propFilterAttributes:
                 if isinstance(attrName, tuple):
-                    allAttrNames.append(attrName[0])
+                    propFilterAttrNames.append(attrName[0])
                 else:
-                    allAttrNames.append(attrName)
-                                    
+                    propFilterAttrNames.append(attrName)
+            propFilterAttrNames = list(set(propFilterAttrNames + searchablePropFilterAttrNames))
+            
             constant = constantProperties.get(propFilter.filter_name)
+            if not searchablePropFilterAttrNames and not constant:
+                # not allAttrNames means propFilter.filter_name is not mapped
+                # return None to try to match all items if this is the only property filter
+                return (None, propFilterAttrNames, [])
+            
             if propFilter.qualifier and isinstance(propFilter.qualifier, addressbookqueryfilter.IsNotDefined):
-                return definedExpression(False, filterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrNames)
+                return definedExpression(False, filterAllOf)
             
             paramFilterElements = [paramFilterElement for paramFilterElement in propFilter.filters if isinstance(paramFilterElement, addressbookqueryfilter.ParameterFilter)]
             textMatchElements = [textMatchElement for textMatchElement in propFilter.filters if isinstance(textMatchElement, addressbookqueryfilter.TextMatch)]
@@ -859,14 +845,13 @@
             if len(paramFilterElements) > 0:
                 if supportedParamter(propFilter.filter_name, paramFilterElements, propFilterAllOf ):
                     if len(textMatchElements) == 0:
-                        return definedExpression(True, filterAllOf, propFilter.filter_name, constant, queryAttributes, allAttrNames)
+                        return definedExpression(True, filterAllOf)
                 else:
                     if propFilterAllOf:
-                        return (False, [], [])
+                        return (False, propFilterAttrNames, [])
             
             # handle text match elements
             propFilterNeedsAllRecords = propFilterAllOf
-            propFilterAttributes = []
             propFilterExpressionList = []
             for textMatchElement in textMatchElements:
                 
@@ -875,7 +860,6 @@
                     propFilterNeedsAllRecords &= textMatchNeedsAllRecords
                 else:
                     propFilterNeedsAllRecords |= textMatchNeedsAllRecords
-                propFilterAttributes += textMatchExpressionAttributes
                 propFilterExpressionList += textMatchExpression
 
 
@@ -884,7 +868,7 @@
             else:
                 propFilterExpressions = list(set(propFilterExpressionList))
             
-            return (propFilterNeedsAllRecords, propFilterAttributes, propFilterExpressions)
+            return (propFilterNeedsAllRecords, propFilterAttrNames, propFilterExpressions)
             #end propFilterExpression
 
         #print("propFilterListQuery: filterAllOf=%r, propFilters=%r" % (filterAllOf, propFilters,))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120419/70b5547c/attachment-0001.html>


More information about the calendarserver-changes mailing list