source: TI12-security/trunk/NDG_XACML/ndg/xacml/core/attributevalue.py @ 6804

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDG_XACML/ndg/xacml/core/attributevalue.py@6804
Revision 6804, 5.1 KB checked in by pjkersha, 9 years ago (diff)

Working class factories for each function module. Function class evaluate methods need to be refactored to accept *AttributeValue? types

Line 
1"""NDG XACML attribute type definition
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "25/02/10"
7__copyright__ = "(C) 2010 Science and Technology Facilities Council"
8__contact__ = "Philip.Kershaw@stfc.ac.uk"
9__license__ = "BSD - see LICENSE file in top-level directory"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = "$Id: $"
12from datetime import datetime, timedelta
13
14from ndg.xacml.utils import VettedDict
15from ndg.xacml.core.expression import Expression
16   
17
18class AttributeValue(Expression):
19    """XACML Attribute Value type"""
20    ELEMENT_LOCAL_NAME = 'AttributeValue'
21    CLASS_NAME_SUFFIX = 'AttributeValue'
22    IDENTIFIER_PREFIX = 'http://www.w3.org/2001/XMLSchema#'
23    IDENTIFIER = None
24    TYPE_MAP = {
25        'String': basestring,
26        'AnyURI': basestring,
27        'Integer': int,
28        'Boolean': bool,
29        'Double': float,
30        'Date': datetime,
31        'DateTime': datetime,
32        'Time': datetime,
33        'DayTimeDuration': timedelta,
34        'YearMonthDuration': timedelta,
35        'X500Name': basestring,
36        'Rfc822Name': basestring,
37        'HexBinary': int,
38        'Base64Binary': NotImplemented,
39        'IpAddress': basestring,
40        'DnsName': basestring
41    }
42    TYPE = None
43   
44    __slots__ = ('__value',) 
45   
46    def __init__(self):
47        super(AttributeValue, self).__init__()
48        if self.__class__.TYPE is None:
49            raise TypeError('TYPE class variable must be set to a valid type '
50                            'in a derived class')
51           
52        self.__value = None
53           
54    def _get_value(self):
55        return self.__value
56
57    def _set_value(self, value):
58        if not isinstance(value, self.__class__.TYPE):
59            raise TypeError('Expecting %r type for "value" '
60                            'attribute; got %r' % (self.__class__.TYPE, 
61                                                   type(value)))
62           
63        self.__value = value 
64
65    value = property(_get_value, _set_value, None, "expression value") 
66   
67    def evaluate(self, context):
68        """Evaluate the result of the expression in a condition
69        @param context: the request context
70        @type context: ndg.xacml.core.context.request.Request
71        @return: attribute value(s) resulting from execution of this expression
72        in a condition
73        @rtype: AttributeValue/NoneType 
74        """ 
75        return self.__value
76
77
78class AttributeValueClassMap(VettedDict):
79    """Specialised dictionary to hold mappings of XML attribute type URIs to
80    their equivalent classes
81    """
82   
83    def __init__(self):
84        """Force entries to derive from AttributeValue and IDs to
85        be string type
86        """       
87        # Filters are defined as staticmethods but reference via self here to
88        # enable derived class to override them as standard methods without
89        # needing to redefine this __init__ method           
90        super(AttributeValueClassMap, self).__init__(self.keyFilter, 
91                                                     self.valueFilter)
92       
93    @staticmethod
94    def keyFilter(key):
95        """Enforce string type keys"""
96        if not isinstance(key, basestring):
97            raise TypeError('Expecting %r type for key; got %r' % 
98                            (basestring, type(key))) 
99        return True 
100   
101    @staticmethod
102    def valueFilter(value):
103        """Enforce AttributeValue derived types for values"""
104
105        if not issubclass(value, AttributeValue):
106            raise TypeError('Expecting %r derived type for value; got %r' % 
107                            (AttributeValue, type(value))) 
108        return True 
109
110
111# Dynamically Create classes based on AttributeValue for all the XACML primitive
112# types
113_IDENTIFIER2CLASS_MAP = AttributeValueClassMap()
114
115for typeName, _type in AttributeValue.TYPE_MAP.items():
116    identifier = AttributeValue.IDENTIFIER_PREFIX + typeName[0
117                                                        ].lower() + typeName[1:]
118
119    className = typeName + AttributeValue.CLASS_NAME_SUFFIX               
120    classVars = {'TYPE': _type, 'IDENTIFIER_NS': identifier}
121   
122    attributeValueClass = type(className, (AttributeValue, ), classVars)
123    AttributeValue.register(attributeValueClass)
124    _IDENTIFIER2CLASS_MAP[identifier] = attributeValueClass
125   
126   
127class AttributeValueClassFactory(object):
128    """Create AttributeValue types based on the XML namespace identifier
129   
130    Convenience wrapper for _IDENTIFIER2CLASS_MAP instance of
131    AttributeValueClassMap
132    """
133    def __init__(self, classMap=None):
134        if classMap is None:
135            self.__classMap = _IDENTIFIER2CLASS_MAP
136        elif isinstance(classMap, AttributeValueClassMap):
137            self.__classMap = classMap
138        else:
139            raise TypeError('Expecting %r derived type for "map" input; got %r'
140                            % (AttributeValueClassMap, type(map)))
141           
142    def __call__(self, identifier):
143        """Return <type>AttributeValue class for given identifier URI or None
144        if no match is found
145        """
146        return self.__classMap.get(identifier)
147       
Note: See TracBrowser for help on using the repository browser.