1 | from zope.component import queryMultiAdapter |
---|
2 | from Products.GenericSetup.interfaces import INode |
---|
3 | from Products.GenericSetup import utils as gsutils |
---|
4 | from ZPublisher.HTTPRequest import default_encoding |
---|
5 | |
---|
6 | import logging |
---|
7 | logger = logging.getLogger('GS adapter') |
---|
8 | |
---|
9 | |
---|
10 | class ATContentAdapterBase(gsutils.XMLAdapterBase, |
---|
11 | gsutils.ObjectManagerHelpers): |
---|
12 | |
---|
13 | _LOGGER_ID = "CacheSetup" |
---|
14 | _encoding = default_encoding |
---|
15 | _fields = None |
---|
16 | |
---|
17 | |
---|
18 | def _getObjectNode(self, name, i18n=True): |
---|
19 | """Override NodeAdapterBase._getObjectNode to use portal_type.""" |
---|
20 | node = self._doc.createElement(name) |
---|
21 | node.setAttribute("name", self.context.getId()) |
---|
22 | node.setAttribute("portal_type", self.context.portal_type) |
---|
23 | i18n_domain = getattr(self.context, "i18n_domain", None) |
---|
24 | if i18n and i18n_domain: |
---|
25 | node.setAttributeNS(gsutils.I18NURI, "i18n:domain", i18n_domain) |
---|
26 | self._i18n_props = ("title", "description") |
---|
27 | return node |
---|
28 | |
---|
29 | |
---|
30 | def _exportNode(self): |
---|
31 | """Export the object as a DOM node. |
---|
32 | """ |
---|
33 | node = self._getObjectNode("object") |
---|
34 | node.appendChild(self._extractFields()) |
---|
35 | node.appendChild(self._extractObjects()) |
---|
36 | return node |
---|
37 | |
---|
38 | |
---|
39 | def _convertValueToString(self, value): |
---|
40 | if isinstance(value, bool): |
---|
41 | value = unicode(bool(value)) |
---|
42 | elif isinstance(value, str): |
---|
43 | value = value.decode(self._encoding) |
---|
44 | elif not isinstance(value, basestring) and value is not None: |
---|
45 | value = unicode(value) |
---|
46 | return value |
---|
47 | |
---|
48 | |
---|
49 | def _extractFields(self): |
---|
50 | fragment = self._doc.createDocumentFragment() |
---|
51 | schema = self.context.Schema() |
---|
52 | for fieldname in self._fields: |
---|
53 | field = schema[fieldname] |
---|
54 | accessor = field.getEditAccessor(self.context) |
---|
55 | if accessor is not None: |
---|
56 | value = accessor() |
---|
57 | else: |
---|
58 | value = field.get(self.context) |
---|
59 | |
---|
60 | node = self._doc.createElement("property") |
---|
61 | node.setAttribute("name", fieldname) |
---|
62 | |
---|
63 | if isinstance(value, (tuple,list)): |
---|
64 | for v in value: |
---|
65 | if isinstance(v, str): |
---|
66 | v = v.decode(self._encoding) |
---|
67 | child = self._doc.createElement("element") |
---|
68 | child.setAttribute("value", v) |
---|
69 | node.appendChild(child) |
---|
70 | else: |
---|
71 | value = self._convertValueToString(value) |
---|
72 | if value is None: |
---|
73 | continue |
---|
74 | child = self._doc.createTextNode(value) |
---|
75 | node.appendChild(child) |
---|
76 | |
---|
77 | if fieldname in getattr(self, "_i18n_props", []): |
---|
78 | node.setAttribute("i18n:translate", "") |
---|
79 | |
---|
80 | fragment.appendChild(node) |
---|
81 | |
---|
82 | return fragment |
---|
83 | |
---|
84 | |
---|
85 | def _purgeFields(self): |
---|
86 | schema = self.context.Schema() |
---|
87 | for fieldname in self._fields: |
---|
88 | field = schema[fieldname] |
---|
89 | field.getMutator(self.context)(field.getDefault(self.context)) |
---|
90 | |
---|
91 | |
---|
92 | def _initFields(self, node): |
---|
93 | schema = self.context.Schema() |
---|
94 | |
---|
95 | for child in node.childNodes: |
---|
96 | if child.nodeName != "property": |
---|
97 | continue |
---|
98 | |
---|
99 | fieldname = str(child.getAttribute("name")) |
---|
100 | if fieldname not in schema.keys(): |
---|
101 | continue |
---|
102 | |
---|
103 | field = schema[fieldname] |
---|
104 | accessor = field.getEditAccessor(self.context) |
---|
105 | if accessor is not None: |
---|
106 | current_value = accessor() |
---|
107 | else: |
---|
108 | current_value = field.get(self.context) |
---|
109 | |
---|
110 | if isinstance(current_value, (list,tuple)): |
---|
111 | if not self._convertToBoolean(child.getAttribute("purge") or "True"): |
---|
112 | value = current_value |
---|
113 | else: |
---|
114 | value = [] |
---|
115 | for sub in child.childNodes: |
---|
116 | if sub.nodeName != "element": |
---|
117 | continue |
---|
118 | value.append(sub.getAttribute("value").encode(self._encoding)) |
---|
119 | |
---|
120 | if isinstance(current_value, tuple): |
---|
121 | value = tuple(value) |
---|
122 | else: |
---|
123 | value = self._getNodeText(child) |
---|
124 | if value == "None": |
---|
125 | value = None |
---|
126 | elif isinstance(current_value, bool): |
---|
127 | value = self._convertToBoolean(value) |
---|
128 | elif isinstance(current_value, int): |
---|
129 | if "Boolean" in field.getType(): |
---|
130 | # Archetypes releases before 1.5.8 had BooleanFields |
---|
131 | # which could return integers. |
---|
132 | value = self._convertToBoolean(value) |
---|
133 | else: |
---|
134 | value = int(value) |
---|
135 | |
---|
136 | field.getMutator(self.context)(value) |
---|
137 | |
---|
138 | |
---|
139 | def _initObjects(self, node): |
---|
140 | """Import objects. This is a much simpler version of |
---|
141 | ObjectManagerHelpers._init_objects which does not support ordering |
---|
142 | and uses portal_types. |
---|
143 | """ |
---|
144 | |
---|
145 | for child in node.childNodes: |
---|
146 | if child.nodeName != "object": |
---|
147 | continue |
---|
148 | |
---|
149 | parent = self.context |
---|
150 | obj_id = str(child.getAttribute("name")) |
---|
151 | if child.hasAttribute("remove"): |
---|
152 | if obj_id in parent.objectIds(): |
---|
153 | parent.manage_delObjects([obj_id]) |
---|
154 | continue |
---|
155 | |
---|
156 | if obj_id not in parent.objectIds(): |
---|
157 | portal_type = str(child.getAttribute("portal_type")) |
---|
158 | self.context.invokeFactory(portal_type, obj_id) |
---|
159 | |
---|
160 | obj = getattr(self.context, obj_id) |
---|
161 | |
---|
162 | importer = queryMultiAdapter((obj, self.environ), INode) |
---|
163 | if importer: |
---|
164 | importer.node = child |
---|
165 | |
---|
166 | |
---|
167 | def _importNode(self, node): |
---|
168 | """Import the object from the DOM node. |
---|
169 | """ |
---|
170 | |
---|
171 | if self.environ.shouldPurge(): |
---|
172 | self._purgeFields() |
---|
173 | self._purgeObjects() |
---|
174 | |
---|
175 | self._initObjects(node) |
---|
176 | self._initFields(node) |
---|
177 | self.context.indexObject() |
---|
178 | |
---|
179 | node = property(_exportNode, _importNode) |
---|
180 | |
---|