source: products/quintagroup.transmogrifier/branches/dictionary/quintagroup/transmogrifier/namespaces/atns.py @ 2720

Last change on this file since 2720 was 2720, checked in by mylan, 14 years ago

Added deserialization for dictionary type fields

File size: 5.3 KB
Line 
1"""
2    Archetypes Marshall namespace but which can safely handle
3    Control Characters for you
4"""
5
6from Products.Archetypes.interfaces.base import IBaseUnit
7
8from Products.Marshall import config
9from Products.Marshall.handlers.atxml import XmlNamespace
10from Products.Marshall.handlers.atxml import SchemaAttribute
11from Products.Marshall.handlers.atxml import getRegisteredNamespaces
12from Products.Marshall.exceptions import MarshallingException
13from Products.Marshall import utils
14
15from Products.Marshall.namespaces import atns as base
16
17from quintagroup.transmogrifier.namespaces.util import has_ctrlchars
18
19_marker = ()
20
21class ATAttribute(base.ATAttribute):
22
23    def serialize(self, dom, parent_node, instance, options={}):
24
25        def getPreparedValue(value):
26            if isinstance(value, unicode):
27                value = value.encode('utf-8')
28            elif IBaseUnit.isImplementedBy(value):
29                value = value.getRaw(encoding='utf-8')
30            else:
31                value = str(value)
32            return value
33
34
35        def addNode(node, value, nspref):
36            if is_ref:
37                if config.HANDLE_REFS:
38                    ref_node = dom.createElementNS(nspref, 'reference')
39                    uid_node = dom.createElementNS(nspref, 'uid')
40                    value = response.createTextNode(value)
41                    uid_node.append(value)
42                    ref_node.append(uid_node)
43                    node.append(ref_node)
44
45            elif isinstance(value, str) and has_ctrlchars(value):
46                value = value.encode('base64')
47                attr = dom.createAttributeNS(nspref, 'transfer_encoding')
48                attr.value = 'base64'
49                node.setAttributeNode(attr)
50                value_node = dom.createCDATASection(value)
51                node.appendChild(value_node)
52            else:
53                value_node = dom.createTextNode(value)
54                node.appendChild(value_node)
55
56        values = self.get(instance)
57        if not values:
58            return
59
60        is_ref = self.isReference(instance)
61       
62        for value in values:
63            node = dom.createElementNS(self.namespace.xmlns, "field")
64            name_attr = dom.createAttribute("name")
65            name_attr.value = self.name
66            node.setAttributeNode(name_attr)
67           
68            # try to get 'utf-8' encoded string
69            items = getattr(value, 'items', _marker)
70            if items is not _marker and callable(items):
71                # Map field
72                # set type attribute for the field
73                type_attr = dom.createAttribute("type")
74                type_attr.value = "dict"
75                node.setAttributeNode(type_attr)
76                for k, v in items():
77                    # create item node with key attribute
78                    good_key = getPreparedValue(k)
79                    item_node = dom.createElementNS(self.namespace.xmlns, "item")
80                    key_attr = dom.createAttribute("key")
81                    key_attr.value = good_key
82                    item_node.setAttributeNode(key_attr)
83                    # prepare value for the item
84                    good_value = getPreparedValue(v)
85                    addNode(item_node, good_value, self.namespace.xmlns)
86                    item_node.normalize()
87                    node.appendChild(item_node)
88            else:
89                # Common field
90                value = getPreparedValue(value)
91                addNode(node, value, self.namespace.xmlns)
92       
93            node.normalize()
94            parent_node.appendChild(node)
95
96        return True
97
98    def processXmlValue(self, context, value):
99        def getValue(node, value):
100            if value is None:
101                return
102            value = value.strip()
103            if not value:
104                return
105            # decode node value if needed
106            te = node.get('transfer_encoding', None)
107            if te is not None:
108                value = value.decode(te)
109            return value
110           
111        # Get value type
112        vtype = context.node.attrib.get('type', None)
113        if vtype=='dict':
114            # process dictionary type
115            d = {}
116            for item in context.node:
117                k = item.get("key", None)
118                v = getValue(item, item.text)
119                if k and v:
120                    d[k] = v
121            value = d
122        else:
123            # Common field
124            value = getValue(context.node, value)
125
126        if not value:
127            return
128
129        data = context.getDataFor(self.namespace.xmlns)
130        if data.has_key(self.name):
131            svalues = data[self.name]
132            if not isinstance(svalues, list):
133                data[self.name] = svalues = [svalues]
134            svalues.append(value)
135            return
136        else:
137            data[self.name] = value
138
139class Archetypes(base.Archetypes):
140
141    def getAttributeByName(self, schema_name, context=None):
142        if context is not None and schema_name not in self.at_fields:
143            if not context.instance.Schema().has_key(schema_name):
144                return
145                raise AssertionError, \
146                      "invalid attribute %s"%(schema_name)
147       
148        if schema_name in self.at_fields:
149            return self.at_fields[schema_name]
150
151        attribute = ATAttribute(schema_name)
152        attribute.setNamespace(self)
153       
154        return attribute
Note: See TracBrowser for help on using the repository browser.