1  import copy 
  2  import string 
  3  from types import * 
  4  from xml.dom.minidom import * 
  5   
  6   
  8      nop = 'wait' 
  9      fields = {'type':{},'actor':{},'object':{},'command':{}, 
 10                '_observed':{},'_unobserved':{}, 
 11                'self':bool , 
 12                'repeatable':bool , 
 13                } 
 14      format = ['actor','type','object','command'] 
 15       
 17          """Translates an action in string form into a structured 
 18          representation of that same action (e.g., 
 19          'CLF-violence-to-UrbanPoor' becomes a PsychAction object 
 20          {'actor':CLF,'type':'violence','object':UrbanPoor}""" 
 21          if type(arg) is StringType: 
 22              raise DeprecationWarning,'PsychAction: Use dictionaries instead of strings (%s) in action creation' % (arg) 
 23          if len(arg) == 0: 
 24              dict.__init__(self,{'type': self.nop}) 
 25          else: 
 26              dict.__init__(self,arg) 
 27          if self['actor'] and not isinstance(self['actor'],str): 
 28              raise TypeError 
 29          if self['object'] and not isinstance(self['object'],str): 
 30              raise TypeError 
 31          self.name = '' 
  32   
 33           
 35          if isinstance(entities,dict): 
 36              for key in self.fields.keys(): 
 37                  if entities.has_key(key): 
 38                      self[key] = entities[key] 
 39          elif type(entities) is ListType: 
 40              for key in self.fields.keys(): 
 41                  for entity in entities: 
 42                      try: 
 43                          if entity.name == self[key]: 
 44                              self[key] = entity 
 45                              break 
 46                      except AttributeError: 
 47                          pass 
 48          else: 
 49              raise TypeError,`type(entities)`+' not supported by '+\ 
 50                    'PsychAgents instantiate method' 
 51          if self['command']: 
 52              self['command'].instantiate(entities) 
  53   
 55          """Returns a list of all possible instantiations of this 
 56          partially specified action.""" 
 57          actList = [self] 
 58          for key,value in self.fields.items(): 
 59              if not self[key]: 
 60                  try: 
 61                      valRange = actType[key] 
 62                  except KeyError: 
 63                      try: 
 64                          valRange = value['range'] 
 65                      except KeyError: 
 66                          continue 
 67                  if len(valRange) > 0: 
 68                      for oldAct in actList[:]: 
 69                          actList.remove(oldAct) 
 70                          for item in valRange: 
 71                              newAct = copy.copy(oldAct) 
 72                              newAct[key] = item 
 73                              actList.append(newAct) 
 74          return actList 
  75   
 77          """Returns a *copy* of this action with the given key,value pair""" 
 78          new = self.__copy__() 
 79          new[key] = value 
 80          return new 
  81       
 83          if self.fields.has_key(index): 
 84              try: 
 85                  return dict.__getitem__(self,index) 
 86              except KeyError: 
 87                  return None 
 88          else: 
 89              raise KeyError,'%s: Unknown field "%s"' \ 
 90                    % (self.__class__.__name__,index) 
  91               
 99               
101          if self.fields.has_key(index): 
102              self[index] = None 
103          else: 
104              raise KeyError,'%s: Unknown field "%s"' \ 
105                    % (self.__class__.__name__,index) 
106          self.name = '' 
 107   
109          list = [] 
110          for key in self.fields.keys(): 
111              if self[key]: 
112                  list.append(key) 
113          return list 
 114   
116          result = {} 
117          for key,value in self.items(): 
118              if isinstance(value,Action): 
119                  result[key] = copy.copy(value) 
120              elif isinstance(value,str): 
121                  result[key] = value 
122              elif type(value) is InstanceType: 
123                  result[key] = value.name 
124              else: 
125                  result[key] = value 
126          result = self.__class__(result) 
127          memo[id(self)] = result 
128          return result 
 129       
131          """Translates a structured dictionary representation of an action 
132          into a standardized string format (e.g., 
133          {'actor':CLF,'type':'violence','object':UrbanPoor} becomes 
134          'CLF-violence-to-UrbanPoor'""" 
135          if len(self.name) == 0: 
136              for key in self.format: 
137                  value = self[key] 
138                  if type(value) is NoneType: 
139                      continue 
140                  if len(self.name) > 0: 
141                      self.name += '-' 
142                  if isinstance(value,str): 
143                      self.name += value 
144                  elif isinstance(value,Action): 
145                      self.name += `value` 
146                  elif type(value) is InstanceType: 
147                      self.name += value.name 
148                  elif type(value) is FloatType: 
149                      self.name += '%6.4f' % (value) 
150          return self.name 
 151   
152 -    def simpleText(self): 
 153          content = self['type'] 
154          if isinstance(self['object'],str): 
155              content += ' %s' % (self['object']) 
156          elif type(self['object']) is InstanceType: 
157              content += ' %s' % (self['object'].name) 
158          return content 
 159   
161         """ 
162         @return: true iff the action matches the given template 
163         @rtype: bool 
164         """ 
165         for key in self.fields: 
166             if template.has_key(key) and template[key]: 
167                 if isinstance(self[key],str): 
168                     if template[key] != self[key]: 
169                          
170                         break 
171                 elif isinstance(self[key],Agent): 
172                     if template[key] != self[key].name: 
173                          
174                         break 
175                 else: 
176                     print 'Unable to match template fields of type:',self[key].__class__.__name__ 
177         else: 
178              
179             return True 
180         return False 
 181   
183          doc = Document() 
184          root = doc.createElement('action') 
185          root.setAttribute('class',self.__class__.__name__) 
186          doc.appendChild(root) 
187          for key,value in self.items(): 
188              if value is not None: 
189                  if isinstance(value,str): 
190                      data = doc.createTextNode(value) 
191                  elif type(value) is InstanceType:  
192                      data = doc.createTextNode(value.name) 
193                  elif isinstance(value,Action): 
194                      data = value.__xml__().documentElement 
195                  elif isinstance(value,bool): 
196                      data = doc.createTextNode(str(value)) 
197                  else: 
198                       
199                      data = None 
200   
201                  if not data is None: 
202                      node = doc.createElement(key) 
203                      root.appendChild(node) 
204                      node.appendChild(data) 
205          return doc 
 206   
208          if doc.nodeType == Node.DOCUMENT_NODE: 
209              root = doc.documentElement 
210          else: 
211              root = doc 
212          clsName = str(root.getAttribute('class')) 
213          if clsName and clsName != self.__class__.__name__: 
214              for cls in self.__class__.__subclasses__(): 
215                  if clsName == cls.__name__: 
216                      obj = cls() 
217                      return obj.parse(doc) 
218              else: 
219                  raise NameError,'Unknown Action subclass: %s' % (clsName) 
220          child = root.firstChild 
221          while child: 
222              if child.nodeType == Node.ELEMENT_NODE: 
223                  key = str(child.tagName) 
224                  grandchild = child.firstChild 
225                  if grandchild and grandchild.nodeType == Node.TEXT_NODE: 
226                      value = string.strip(str(child.firstChild.data)) 
227                      if self.fields.has_key(key): 
228                          if self.fields[key] is bool: 
229                              if value == 'True': 
230                                  value = True 
231                              else: 
232                                  value = False 
233                          self[key] = value 
234              child = child.nextSibling 
235          return self 
 236   
 239       
241      """ 
242      Class for specifying a template for matching joint actions 
243      @ivar verbs: dictionary of verbs that this condition matches 
244      @type verbs: strS{->}C{True} 
245      @ivar only: C{True} iff only actions in the verb set are allowed (default is C{False}) 
246      @type only: bool 
247      @ivar count: C{True} iff we are interested in how many actions match, not just a boolean value (default is C{False}) 
248      @type count: bool 
249      """ 
250 -    def __init__(self,only=False,count=False): 
 251          self.verbs = {} 
252          self.only = only 
253          self.count = count 
 254   
256          self.verbs[verb] = True 
 257   
260   
262          return len(self.verbs) 
 263   
264 -    def match(self,actions): 
 265          """ 
266          @return: If C{self.count} is C{False}, then return C{True} iff the given joint action meets this condition; otherwise, return number of matching actions, or 0 if match fails 
267          @rtype: bool or int 
268          """ 
269          if isinstance(actions,dict): 
270               
271              actions = sum(actions.values(),[]) 
272          match = {}  
273          if self.only: 
274               
275              for action in actions: 
276                  if self.verbs.has_key(action['type']): 
277                      match[action['type']] = True 
278                  elif self.count: 
279                      return 0 
280                  else: 
281                      return False 
282               
283              if self.count: 
284                  return len(actions) 
285              else: 
286                  return len(match) == len(self.verbs) 
287          elif self.count: 
288               
289              count = 0 
290              for action in actions: 
291                  if self.verbs.has_key(action['type']): 
292                      match[action['type']] = True 
293                      count += 1 
294              if len(match) == len(self.verbs): 
295                  return count 
296              else: 
297                  return 0 
298          else: 
299               
300              index = 0 
301              while len(match) < len(self.verbs): 
302                  if index < len(actions): 
303                      if self.verbs.has_key(actions[index]['type']): 
304                          match[actions[index]['type']] = True 
305                      index += 1 
306                  else: 
307                       
308                      break 
309               
310              return len(match) == len(self.verbs) 
 311   
313          if self.only: 
314              return 'Only '+','.join(self.verbs.keys()) 
315          elif len(self.verbs) == 0: 
316              return 'Any' 
317          else: 
318              return ','.join(self.verbs.keys()) 
 319   
321          doc = Document() 
322          root = doc.createElement('condition') 
323          doc.appendChild(root) 
324          root.setAttribute('only',str(self.only)) 
325          root.setAttribute('count',str(self.count)) 
326          for verb in self.verbs.keys(): 
327              if self.verbs[verb]: 
328                  node = doc.createElement('verb') 
329                  node.appendChild(doc.createTextNode(verb)) 
330                  root.appendChild(node) 
331          return doc 
 332   
333 -    def parse(self,element): 
 334          self.verbs.clear() 
335          self.only = str(element.getAttribute('only')).lower() == 'true' 
336          self.count = str(element.getAttribute('count')).lower() == 'true' 
337          node = element.firstChild 
338          while node: 
339              if node.nodeType == node.ELEMENT_NODE: 
340                  assert str(node.tagName) == 'verb' 
341                  child = node.firstChild 
342                  while child: 
343                      if child.nodeType == child.TEXT_NODE: 
344                          self.verbs[str(child.data).strip()] = True 
345                      child = child.nextSibling 
346              node = node.nextSibling 
  347   
348               
349  if __name__ == '__main__': 
350      import os.path 
351       
352   
353      act = Action({'actor':'CortinaGov','type':'wait'}) 
354      name = '/tmp/%s.xml' % (os.path.basename(__file__)) 
355      file = open(name,'w') 
356      file.write(act.__xml__().toxml()) 
357      file.close() 
358   
359      new = Action() 
360      new.parse(parse(name)) 
361      print new 
362