comparison orpg/mapper/base_msg.py @ 0:4385a7d0efd1 grumpy-goblin

Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author sirebral
date Tue, 14 Jul 2009 16:41:58 -0500
parents
children 78407d627cba
comparison
equal deleted inserted replaced
-1:000000000000 0:4385a7d0efd1
1 # Copyright (C) 2000-2001 The OpenRPG Project
2 #
3 # openrpg-dev@lists.sourceforge.net
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 # --
19 #
20 # File: mapper/base_msg.py
21 # Author: Chris Davis
22 # Maintainer:
23 # Version:
24 # $Id: base_msg.py,v 1.9 2007/03/09 14:11:55 digitalxero Exp $
25 #
26 # Description:
27 #
28 __version__ = "$Id: base_msg.py,v 1.9 2007/03/09 14:11:55 digitalxero Exp $"
29
30 from threading import RLock
31 from orpg.networking.mplay_client import *
32
33 class map_element_msg_base:
34 # This is a base class
35
36 def __init__(self,reentrant_lock_object = None):
37
38 if not hasattr(self,"tagname"):
39 raise Exception, "This is a virtual class that cannot be directly instantiated. Set self.tagname in derived class."
40
41 self._props = {}
42 # This is a dictionary that holds (value,changed) 2-tuples, indexed by attribute
43 # Avoid manipulating these values directly. Instead, use the provided accessor methods.
44 # If there is not one that suits your needs, please add one to this class and
45 # use it instead.
46
47 self.children = {}
48 # This next clause will set self.p_lock to a passed-in RLock object, if present.
49 # Otherwise, it will create it's very own for this instance.
50 # Using a passed in object is useful to protect an entire <map/> element from
51 # being changed by another thread when any part of it is being change by another
52 # thread. Just pass the map_msg's p_lock object in to it's descendents.
53 if reentrant_lock_object:
54 self.p_lock = reentrant_lock_object
55 else:
56 self.p_lock = RLock()
57
58 def clear(self):
59 self.p_lock.acquire()
60
61 for child in self.children.keys():
62 self.children[child].clear()
63 self.children[child] = None
64 del self.children[child]
65
66 for p in self._props.keys():
67 self._props[p] = None
68
69 self.p_lock.release()
70
71
72 #########################################
73 # Accessor functions begin
74
75 # Access single property
76
77 def init_prop(self,prop,value): # set's the changed flag to False and assigns
78 self.p_lock.acquire()
79 self._props[prop] = (value, 0)
80 self.p_lock.release()
81
82 def set_prop(self,prop,value): # set's the changed flag to True and assigns
83 self.p_lock.acquire()
84 self._props[prop] = (value, 1)
85 self.p_lock.release()
86
87 def get_prop(self,prop): # returns None if prop not found
88 self.p_lock.acquire()
89 if prop in self._props.keys():
90 (p,c) = self._props[prop]
91 self.p_lock.release()
92 return p
93 else:
94 self.p_lock.release()
95 return None
96
97 def is_prop_changed(self,prop): # returns None if prop not found
98 self.p_lock_acquire()
99 if prop in self._props.keys():
100 (p,c) = self._props[prop]
101 self.p_lock.release()
102 return c
103 else:
104 self.p_lock.release()
105 return None
106
107 def get_child(self,key): # returns None if key not found in children list
108 self.p_lock_acquire()
109 if self.children.has_key(key):
110 self.p_lock.release()
111 return self.children[key]
112 else:
113 self.p_lock.release()
114 return None
115
116 # Access multiple properties
117
118 def init_props(self,props): # same as init_prop(), but takes dictionary of props
119 self.p_lock.acquire()
120 for k in props.keys():
121 self._props[k] = (props[k],0)
122 self.p_lock.release()
123
124 def set_props(self,props): # same as set_prop(), but takes dictionary of props
125 self.p_lock.acquire()
126 for k in props.keys():
127 self._props[k] = (props[k],1)
128 self.p_lock.release()
129
130 def get_all_props(self): # returns dictionary of all properties, regardless of change
131 self.p_lock.acquire()
132
133 result = {}
134 for k in self._props.keys():
135 (p,c) = self._props[k]
136 result[k] = p
137
138 self.p_lock.release()
139 return result
140
141 def get_changed_props(self): # returns dictionary of all properties that have been changed
142 self.p_lock.acquire()
143 result = {}
144 for k in self._props.keys():
145 (p,c) = self._props[k]
146 if c:
147 result[k] = p
148 self.p_lock.release()
149 return result
150
151 def get_children(self): # returns dictionary of children
152 return self.children
153
154
155 # Accessor functions end
156 #########################################
157
158 #########################################
159 # XML emitters begin
160 def get_all_xml(self,action="new",output_action = 0): # outputs a tag with all attributes it contains
161 self.p_lock.acquire()
162 xml_str = "<" + self.tagname
163 if action and output_action:
164 xml_str += " action='" + action + "'"
165 for k in self._props.keys():
166 (p,c) = self._props[k]
167 if k != "action" or not action:
168 xml_str += " " + k + "='" + p + "'"
169 if self.children:
170 xml_str += ">"
171 for child in self.children.keys():
172 xml_str += self.children[child].get_all_xml(action)
173 xml_str += "</" + self.tagname + ">"
174 else:
175 xml_str += "/>"
176 self.p_lock.release()
177 return xml_str
178
179 def get_changed_xml(self,action="update",output_action = 0): # outputs a tag with all changed attributes
180 self.p_lock.acquire()
181 xml_str = "<" + self.tagname
182 if action and output_action:
183 xml_str += " action='" + action + "'"
184
185 # if present, always send the id, even if it didn't change
186 if self._props.has_key("id"):
187 (p,c) = self._props["id"]
188 xml_str += " id='" + p + "'"
189 for k in self._props.keys():
190 (p,c) = self._props[k]
191 if (k != "id" or k != "action") and c == 1: # don't duplicate the id attribute
192 xml_str += " " + k + "='" + p + "'"
193 if self.children:
194 xml_str += ">"
195 for child in self.children.keys():
196 xml_str += self.children[child].get_changed_xml(action)
197 xml_str += "</" + self.tagname + ">"
198 else:
199 xml_str += "/>"
200 self.p_lock.release()
201 return xml_str
202
203 # convenience method to use if only this tag is modified
204 # outputs a <map/> element containing only the changes to this tag
205 def standalone_update_text(self,update_id_string):
206 buffer = "<map id='" + update_id_string + "'>"
207 buffer += self.get_changed_xml("update")
208 buffer += "<map/>"
209 return buffer
210
211 # XML emitters end
212 #########################################
213
214 #########################################
215 # XML importers begin
216
217 def _from_dom(self,xml_dom,prop_func):
218 self.p_lock.acquire()
219 if xml_dom.tagName == self.tagname:
220 if xml_dom.getAttributeKeys():
221 for k in xml_dom.getAttributeKeys():
222 prop_func(k,xml_dom.getAttribute(k))
223 else:
224 self.p_lock.release()
225 raise Exception, "Error attempting to modify a " + self.tagname + " from a non-<" + self.tagname + "/> element"
226 self.p_lock.release()
227
228 def init_from_dom(self,xml_dom):
229 # xml_dom must be pointing to an empty tag. Override in a derived class for <map/> and other similar tags.
230 self._from_dom(xml_dom,self.init_prop)
231
232 def set_from_dom(self,xml_dom):
233 # xml_dom must be pointing to an empty tag. Override in a derived class for <map/> and other similar tags
234 self._from_dom(xml_dom,self.set_prop)
235
236 def init_from_xml(self,xml):
237 xml_dom = parseXml(xml)
238 node_list = xml_dom.getElementsByTagName(self.tagname)
239 if len(node_list) < 1:
240 print "Warning: no <" + self.tagname + "/> elements found in DOM."
241 else:
242 while len(node_list):
243 self.init_from_dom(node_list.pop())
244 if xml_dom:
245 xml_dom.unlink()
246
247 def set_from_xml(self,xml):
248 xml_dom = parseXml(xml)
249 node_list = xml_dom.getElementsByTagName(self.tagname)
250 if len(node_list) < 1:
251 print "Warning: no <" + self.tagname + "/> elements found in DOM."
252 else:
253 while len(node_list):
254 self.set_from_dom(node_list.pop())
255 if xml_dom:
256 xml_dom.unlink()
257
258 # XML importers end
259 #########################################