15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""" Hierarchical property system for IDL AST """
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_log import ErrOut, InfoOut, WarnOut
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLPropertyNode
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A property node is a hierarchically aware system for mapping
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# keys to values, such that a local dictionary is search first,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# followed by parent dictionaries in order.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLPropertyNode(object):
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self):
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.parents = []
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.property_map = {}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def AddParent(self, parent):
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert parent
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.parents.append(parent)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SetProperty(self, name, val):
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.property_map[name] = val
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  def GetProperty(self, name):
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Check locally for the property, and return it if found.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prop = self.property_map.get(name, None)
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if prop is not None:
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return prop
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If not, seach parents in order
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for parent in self.parents:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prop = parent.GetProperty(name)
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if prop is not None:
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return prop
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Otherwise, it can not be found.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  def GetPropertyLocal(self, name):
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    # Search for the property, but only locally.
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return self.property_map.get(name, None)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetPropertyList(self):
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self.property_map.keys()
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Testing functions
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Build a property node, setting the properties including a name, and
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# associate the children with this new node.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)def BuildNode(name, props, children=None, parents=None):
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  node = IDLPropertyNode()
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  node.SetProperty('NAME', name)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for prop in props:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    toks = prop.split('=')
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node.SetProperty(toks[0], toks[1])
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if children:
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for child in children:
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      child.AddParent(node)
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if parents:
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for parent in parents:
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      node.AddParent(parent)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return node
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ExpectProp(node, name, val):
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  found = node.GetProperty(name)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if found != val:
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ErrOut.Log('Got property %s expecting %s' % (found, val))
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Verify property inheritance
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def PropertyTest():
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors = 0
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left = BuildNode('Left', ['Left=Left'])
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  right = BuildNode('Right', ['Right=Right'])
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top = BuildNode('Top', ['Left=Top', 'Right=Top'], [left, right])
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors += ExpectProp(top, 'Left', 'Top')
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors += ExpectProp(top, 'Right', 'Top')
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors += ExpectProp(left, 'Left', 'Left')
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors += ExpectProp(left, 'Right', 'Top')
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors += ExpectProp(right, 'Left', 'Top')
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors += ExpectProp(right, 'Right', 'Right')
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if not errors:
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    InfoOut.Log('Passed PropertyTest')
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return errors
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def Main():
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors = 0
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors += PropertyTest()
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if errors:
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ErrOut.Log('IDLNode failed with %d errors.' % errors)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return  -1
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys.exit(Main())
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115