Mercurial > traipse_dev
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/orpg/mapper/base_msg.py Tue Jul 14 16:41:58 2009 -0500 @@ -0,0 +1,259 @@ +# Copyright (C) 2000-2001 The OpenRPG Project +# +# openrpg-dev@lists.sourceforge.net +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# -- +# +# File: mapper/base_msg.py +# Author: Chris Davis +# Maintainer: +# Version: +# $Id: base_msg.py,v 1.9 2007/03/09 14:11:55 digitalxero Exp $ +# +# Description: +# +__version__ = "$Id: base_msg.py,v 1.9 2007/03/09 14:11:55 digitalxero Exp $" + +from threading import RLock +from orpg.networking.mplay_client import * + +class map_element_msg_base: +# This is a base class + + def __init__(self,reentrant_lock_object = None): + + if not hasattr(self,"tagname"): + raise Exception, "This is a virtual class that cannot be directly instantiated. Set self.tagname in derived class." + + self._props = {} + # This is a dictionary that holds (value,changed) 2-tuples, indexed by attribute + # Avoid manipulating these values directly. Instead, use the provided accessor methods. + # If there is not one that suits your needs, please add one to this class and + # use it instead. + + self.children = {} + # This next clause will set self.p_lock to a passed-in RLock object, if present. + # Otherwise, it will create it's very own for this instance. + # Using a passed in object is useful to protect an entire <map/> element from + # being changed by another thread when any part of it is being change by another + # thread. Just pass the map_msg's p_lock object in to it's descendents. + if reentrant_lock_object: + self.p_lock = reentrant_lock_object + else: + self.p_lock = RLock() + + def clear(self): + self.p_lock.acquire() + + for child in self.children.keys(): + self.children[child].clear() + self.children[child] = None + del self.children[child] + + for p in self._props.keys(): + self._props[p] = None + + self.p_lock.release() + + + ######################################### + # Accessor functions begin + + # Access single property + + def init_prop(self,prop,value): # set's the changed flag to False and assigns + self.p_lock.acquire() + self._props[prop] = (value, 0) + self.p_lock.release() + + def set_prop(self,prop,value): # set's the changed flag to True and assigns + self.p_lock.acquire() + self._props[prop] = (value, 1) + self.p_lock.release() + + def get_prop(self,prop): # returns None if prop not found + self.p_lock.acquire() + if prop in self._props.keys(): + (p,c) = self._props[prop] + self.p_lock.release() + return p + else: + self.p_lock.release() + return None + + def is_prop_changed(self,prop): # returns None if prop not found + self.p_lock_acquire() + if prop in self._props.keys(): + (p,c) = self._props[prop] + self.p_lock.release() + return c + else: + self.p_lock.release() + return None + + def get_child(self,key): # returns None if key not found in children list + self.p_lock_acquire() + if self.children.has_key(key): + self.p_lock.release() + return self.children[key] + else: + self.p_lock.release() + return None + + # Access multiple properties + + def init_props(self,props): # same as init_prop(), but takes dictionary of props + self.p_lock.acquire() + for k in props.keys(): + self._props[k] = (props[k],0) + self.p_lock.release() + + def set_props(self,props): # same as set_prop(), but takes dictionary of props + self.p_lock.acquire() + for k in props.keys(): + self._props[k] = (props[k],1) + self.p_lock.release() + + def get_all_props(self): # returns dictionary of all properties, regardless of change + self.p_lock.acquire() + + result = {} + for k in self._props.keys(): + (p,c) = self._props[k] + result[k] = p + + self.p_lock.release() + return result + + def get_changed_props(self): # returns dictionary of all properties that have been changed + self.p_lock.acquire() + result = {} + for k in self._props.keys(): + (p,c) = self._props[k] + if c: + result[k] = p + self.p_lock.release() + return result + + def get_children(self): # returns dictionary of children + return self.children + + + # Accessor functions end + ######################################### + + ######################################### + # XML emitters begin + def get_all_xml(self,action="new",output_action = 0): # outputs a tag with all attributes it contains + self.p_lock.acquire() + xml_str = "<" + self.tagname + if action and output_action: + xml_str += " action='" + action + "'" + for k in self._props.keys(): + (p,c) = self._props[k] + if k != "action" or not action: + xml_str += " " + k + "='" + p + "'" + if self.children: + xml_str += ">" + for child in self.children.keys(): + xml_str += self.children[child].get_all_xml(action) + xml_str += "</" + self.tagname + ">" + else: + xml_str += "/>" + self.p_lock.release() + return xml_str + + def get_changed_xml(self,action="update",output_action = 0): # outputs a tag with all changed attributes + self.p_lock.acquire() + xml_str = "<" + self.tagname + if action and output_action: + xml_str += " action='" + action + "'" + + # if present, always send the id, even if it didn't change + if self._props.has_key("id"): + (p,c) = self._props["id"] + xml_str += " id='" + p + "'" + for k in self._props.keys(): + (p,c) = self._props[k] + if (k != "id" or k != "action") and c == 1: # don't duplicate the id attribute + xml_str += " " + k + "='" + p + "'" + if self.children: + xml_str += ">" + for child in self.children.keys(): + xml_str += self.children[child].get_changed_xml(action) + xml_str += "</" + self.tagname + ">" + else: + xml_str += "/>" + self.p_lock.release() + return xml_str + + # convenience method to use if only this tag is modified + # outputs a <map/> element containing only the changes to this tag + def standalone_update_text(self,update_id_string): + buffer = "<map id='" + update_id_string + "'>" + buffer += self.get_changed_xml("update") + buffer += "<map/>" + return buffer + + # XML emitters end + ######################################### + + ######################################### + # XML importers begin + + def _from_dom(self,xml_dom,prop_func): + self.p_lock.acquire() + if xml_dom.tagName == self.tagname: + if xml_dom.getAttributeKeys(): + for k in xml_dom.getAttributeKeys(): + prop_func(k,xml_dom.getAttribute(k)) + else: + self.p_lock.release() + raise Exception, "Error attempting to modify a " + self.tagname + " from a non-<" + self.tagname + "/> element" + self.p_lock.release() + + def init_from_dom(self,xml_dom): + # xml_dom must be pointing to an empty tag. Override in a derived class for <map/> and other similar tags. + self._from_dom(xml_dom,self.init_prop) + + def set_from_dom(self,xml_dom): + # xml_dom must be pointing to an empty tag. Override in a derived class for <map/> and other similar tags + self._from_dom(xml_dom,self.set_prop) + + def init_from_xml(self,xml): + xml_dom = parseXml(xml) + node_list = xml_dom.getElementsByTagName(self.tagname) + if len(node_list) < 1: + print "Warning: no <" + self.tagname + "/> elements found in DOM." + else: + while len(node_list): + self.init_from_dom(node_list.pop()) + if xml_dom: + xml_dom.unlink() + + def set_from_xml(self,xml): + xml_dom = parseXml(xml) + node_list = xml_dom.getElementsByTagName(self.tagname) + if len(node_list) < 1: + print "Warning: no <" + self.tagname + "/> elements found in DOM." + else: + while len(node_list): + self.set_from_dom(node_list.pop()) + if xml_dom: + xml_dom.unlink() + + # XML importers end + #########################################