1 /**
2 * Inkboard message -> XML::Event* deserializer
3 *
4 * Authors:
5 * David Yip <yipdw@rose-hulman.edu>
6 *
7 * Copyright (c) 2005 Authors
8 *
9 * Released under GNU GPL, read the file 'COPYING' for more information
10 */
12 #ifndef __WHITEBOARD_MESSAGE_DESERIALIZER_H__
13 #define __WHITEBOARD_MESSAGE_DESERIALIZER_H__
15 #include "xml/log-builder.h"
16 #include "xml/event.h"
18 #include "jabber_whiteboard/node-tracker-event-tracker.h"
19 #include "jabber_whiteboard/node-tracker.h"
20 #include "jabber_whiteboard/typedefs.h"
22 #include <functional>
23 #include <algorithm>
24 #include <glibmm.h>
26 namespace Inkscape {
28 namespace Whiteboard {
30 /**
31 * A stateful XML::Event deserializer.
32 *
33 * The Deserializer class is meant to deserialize XML::Events serialized by
34 * Inkscape::Whiteboard::Serializer or a serializer that serializes
35 * XML::Events into the same format.
36 *
37 * Usage is as follows:
38 * <ol>
39 * <li>For each serialized event called, call the appropriate deserialization method.</li>
40 * <li>Detach the deserialized event.</li>
41 * </ol>
42 *
43 * The deserializer does not actually modify any aspect of the document or node-tracking systems.
44 * Methods are provided to provide the information necessary to perform the modifications outside
45 * of the deserializer.
46 */
47 class Deserializer {
48 public:
49 /**
50 * Constructor.
51 *
52 * \param xnt The XMLNodeTracker that a Deserializer should use for retrieving
53 * XML::Nodes based on string keys.
54 */
55 Deserializer(XMLNodeTracker* xnt) : _xnt(xnt)
56 {
57 this->clearEventLog();
58 }
60 ~Deserializer() { }
62 /**
63 * Deserialize a node add event.
64 *
65 * \see XML::EventAdd
66 * \param msg The message that describes the event.
67 */
68 void deserializeEventAdd(Glib::ustring const& msg);
70 /**
71 * Deserialize a node remove event.
72 *
73 * \see XML::EventDel
74 * \param msg The message that describes the event.
75 */
76 void deserializeEventDel(Glib::ustring const& msg);
78 /**
79 * Deserialize a node order change event.
80 *
81 * \see XML::EventChgOrder
82 * \param msg The message that describes the event.
83 */
84 void deserializeEventChgOrder(Glib::ustring const& msg);
86 /**
87 * Deserialize a node content change event.
88 *
89 * \see XML::EventChgContent
90 * \param msg The message that describes the event.
91 */
92 void deserializeEventChgContent(Glib::ustring const& msg);
94 /**
95 * Deserialize a node attribute change event.
96 *
97 * \see XML::EventChgAttr
98 * \param msg The message that describes the event.
99 */
100 void deserializeEventChgAttr(Glib::ustring const& msg);
102 /**
103 * Retrieve the deserialized event log.
104 * This method does <b>not</b> clear the internal event log kept by the deserializer.
105 * To do that, use detachEventLog.
106 *
107 * \return The deserialized event log.
108 */
109 XML::Event* getEventLog()
110 {
111 return this->_log;
112 }
114 /**
115 * Retrieve the deserialized event log and clear the internal event log kept by the deserializer.
116 *
117 * \return The deserialized event log.
118 */
119 XML::Event* detachEventLog()
120 {
121 XML::Event* ret = this->_log;
122 this->clearEventLog();
123 return ret;
124 }
126 /**
127 * Clear the internal event log.
128 */
129 void clearEventLog()
130 {
131 g_log(NULL, G_LOG_LEVEL_DEBUG, "Clearing event log");
132 this->_log = NULL;
133 }
135 /**
136 * Retrieve a list of node entry actions (add node entry, remove node entry)
137 * that need to be performed on the XMLNodeTracker.
138 *
139 * Because this method returns a reference to a list, it is not safe for use
140 * across multiple invocations of this Deserializer.
141 *
142 * \return A reference to a list of node entry actions generated while deserializing.
143 */
144 KeyToNodeActionList& getNodeTrackerActions()
145 {
146 return this->_actions;
147 }
149 /**
150 * Retrieve a list of node entry actions (add node entry, remove node entry)
151 * that need to be performed on the XMLNodeTracker.
152 *
153 * \return A list of node entry actions generated while deserializing.
154 */
155 KeyToNodeActionList getNodeTrackerActionsCopy()
156 {
157 return this->_actions;
158 }
160 /**
161 * Retrieve a set of nodes for which an EventChgAttr was deserialized.
162 *
163 * For some actions (i.e. text tool) it is necessary to call updateRepr() on
164 * the updated nodes. This method provides the information required to perform
165 * that action.
166 *
167 * Because this method returns a reference to a set, it is not safe for use
168 * across multiple invocations of this Deserializer.
169 *
170 * \return A reference to a set of nodes for which an EventChgAttr was deserialized.
171 */
172 AttributesUpdatedSet& getUpdatedAttributeNodeSet()
173 {
174 return this->_updated;
175 }
177 /**
178 * Retrieve a set of nodes for which an EventChgAttr was deserialized.
179 *
180 * For some actions (i.e. text tool) it is necessary to call updateRepr() on
181 * the updated nodes. This method provides the information required to perform
182 * that action.
183 *
184 * \return A set of nodes for which an EventChgAttr was deserialized.
185 */
186 AttributesUpdatedSet getUpdatedAttributeNodeSetCopy()
187 {
188 return this->_updated;
189 }
191 /**
192 * Clear all internal node buffers.
193 */
194 void clearNodeBuffers()
195 {
196 g_log(NULL, G_LOG_LEVEL_DEBUG, "Clearing deserializer node buffers");
197 this->_newnodes.clear();
198 this->_actions.clear();
199 this->_newkeys.clear();
200 this->_parent_child_map.clear();
201 this->_updated.clear();
202 }
204 /**
205 * Clear all internal state.
206 */
207 void reset()
208 {
209 this->clearEventLog();
210 this->clearNodeBuffers();
211 }
213 private:
214 XML::Node* _getNodeByID(std::string const& id)
215 {
216 KeyToNodeMap::iterator i = this->_newnodes.find(id);
217 if (i != this->_newnodes.end()) {
218 return const_cast< XML::Node* >(i->second);
219 } else {
220 if (this->_xnt->isTracking(id)) {
221 return this->_xnt->get(id);
222 } else {
223 return NULL;
224 }
225 }
226 }
228 void _addOneEvent(XML::Event* event)
229 {
230 if (this->_log == NULL) {
231 this->_log = event;
232 } else {
233 event->next = this->_log;
234 this->_log = event;
235 }
236 }
238 void _recursiveMarkForRemoval(XML::Node* node);
240 // internal states with accessors:
242 // node tracker actions (add node, remove node)
243 KeyToNodeActionList _actions;
245 // nodes that have had their attributes updated
246 AttributesUpdatedSet _updated;
248 // the deserialized event log
249 XML::Event* _log;
252 // for internal use:
254 // These maps only store information on a single node. That's fine, though;
255 // all we care about is the ability to do key <-> node association. The NodeTrackerEventTracker
256 // and KeyToNodeActionList keep track of the actual actions we need to perform
257 // on the node tracker.
258 NodeToKeyMap _newkeys;
259 KeyToNodeMap _newnodes;
260 NodeTrackerEventTracker _node_action_tracker;
262 typedef std::map< XML::Node*, XML::Node* > _pc_map_type;
263 _pc_map_type _parent_child_map;
265 XMLNodeTracker* _xnt;
267 XML::LogBuilder _builder;
268 };
270 }
272 }
274 #endif
276 /*
277 Local Variables:
278 mode:c++
279 c-file-style:"stroustrup"
280 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
281 indent-tabs-mode:nil
282 fill-column:99
283 End:
284 */
285 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :