source: products/quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/marshall.py @ 1589

Last change on this file since 1589 was 1414, checked in by piv, 14 years ago

merge plone2.1 branche updates (r2426-2428,2433-2452): manifests with valid xml now, binary files fully dumped, local roles are imported, control characters are handled properly

File size: 6.0 KB
Line 
1import traceback
2from DateTime import DateTime
3
4from zope.interface import classProvides, implements
5from zope import event
6
7from ZODB.POSException import ConflictError
8
9from collective.transmogrifier.interfaces import ISection, ISectionBlueprint
10from collective.transmogrifier.utils import defaultMatcher
11
12from Products.CMFCore import utils
13from Products.Marshall import registry
14from Products.Archetypes.interfaces import IBaseObject
15from Products.Archetypes.event import ObjectInitializedEvent
16from Products.Archetypes.event import ObjectEditedEvent
17
18# override Marshall atxml namespaces
19from quintagroup.transmogrifier import namespaces
20
21
22class MarshallerSection(object):
23    classProvides(ISectionBlueprint)
24    implements(ISection)
25
26    def __init__(self, transmogrifier, name, options, previous):
27        self.previous = previous
28        self.context = transmogrifier.context
29
30        self.pathkey = defaultMatcher(options, 'path-key', name, 'path')
31        self.fileskey = options.get('files-key', '_files').strip()
32
33        self.excludekey = defaultMatcher(options, 'exclude-key', name, 'excluded_fields')
34        self.exclude = filter(None, [i.strip() for i in 
35                              options.get('exclude', '').splitlines()])
36
37        self.atxml = registry.getComponent("atxml")
38
39    def __iter__(self):
40        for item in self.previous:
41            pathkey = self.pathkey(*item.keys())[0]
42
43            if not pathkey:
44                yield item; continue
45
46            path = item[pathkey]
47            obj = self.context.unrestrictedTraverse(path, None)
48            if obj is None:         # path doesn't exist
49                yield item; continue
50
51            if IBaseObject.providedBy(obj):
52                # get list of excluded fields given in options and in item
53                excludekey = self.excludekey(*item.keys())[0]
54                atns_exclude = tuple(self.exclude)
55                if excludekey:
56                    atns_exclude = tuple(set(item[excludekey]) | set(atns_exclude))
57
58                try:
59                    content_type, length, data = self.atxml.marshall(obj, atns_exclude=atns_exclude)
60                except ConflictError:
61                    raise
62                except:
63                    data = None
64
65                if data or data is None:
66                    # None value has special meaning for IExportDataCorrector adapter for topic criterias
67                    files = item.setdefault(self.fileskey, {})
68                    item[self.fileskey]['marshall'] = {
69                        'name': '.marshall.xml',
70                        'data': data,
71                    }
72
73            yield item
74
75class DemarshallerSection(object):
76    classProvides(ISectionBlueprint)
77    implements(ISection)
78
79    def __init__(self, transmogrifier, name, options, previous):
80        self.previous = previous
81        self.context = transmogrifier.context
82
83        self.pathkey = defaultMatcher(options, 'path-key', name, 'path')
84        self.fileskey = defaultMatcher(options, 'files-key', name, 'files')
85
86        # Marshall doesn't support excluding fields on demarshalling,
87        # we can do this with xml.dom.minodom, if it'll be needed in the future
88        # self.excludekey = defaultMatcher(options, 'exclude-key', name, 'excluded_fields')
89
90        # self.exclude = filter(None, [i.strip() for i in
91        #                     options.get('exclude', '').splitlines()])
92
93        self.atxml = registry.getComponent("atxml")
94
95    def __iter__(self):
96        for item in self.previous:
97            pathkey = self.pathkey(*item.keys())[0]
98            fileskey = self.fileskey(*item.keys())[0]
99
100            if not (pathkey and fileskey):
101                yield item; continue
102            if 'marshall' not in item[fileskey]:
103                yield item; continue
104
105            path = item[pathkey]
106            obj = self.context.unrestrictedTraverse(path, None)
107            if obj is None:         # path doesn't exist
108                yield item; continue
109
110            if IBaseObject.providedBy(obj):
111                try:
112                    data = item[fileskey]['marshall']['data']
113                    self.atxml.demarshall(obj, data)
114
115                    # When we change workflow state of content through Plone interface,
116                    # effective date field will be updated to current date (the same
117                    # as modification date) if it was empty, so after demarshalling
118                    # (workflow history was updated) we need to do it manually.
119                    effective_field = obj.getField('effectiveDate')
120                    if effective_field is not None and effective_field.getAccessor(obj)() is None:
121                        date = obj.getField('modification_date').getAccessor(obj)()
122                        effective_field.getMutator(obj)(date)
123
124                    # we don't want to call reindexObject because modification_date
125                    # will be updated, so we call only indexObject (reindexObject does
126                    # some things with uid catalog too)
127                    is_new_object = obj.checkCreationFlag()
128                    obj.indexObject()
129                    # firing of events
130                    obj.unmarkCreationFlag()
131                    if is_new_object:
132                        event.notify(ObjectInitializedEvent(obj))
133                        obj.at_post_create_script()
134                    else:
135                        event.notify(ObjectEditedEvent(obj))
136                        obj.at_post_edit_script()
137                except ConflictError:
138                    raise
139                except Exception, e:
140                    print 'Exception in demarshaller section:'
141                    print '-'*60
142                    traceback.print_exc()
143                    print '-'*60
144
145            yield item
146
147        # updating security settings on demarshalled content
148        wtool = utils.getToolByName(self.context, 'portal_workflow')
149        wtool.updateRoleMappings()
150        catalog = utils.getToolByName(self.context, 'portal_catalog')
151        catalog.reindexIndex('allowedRolesAndUsers', None)
Note: See TracBrowser for help on using the repository browser.