buildframework/helium/tools/common/python/lib/configuration_model.py
changeset 1 be27ed110b50
child 179 d8ac696cc51f
equal deleted inserted replaced
0:044383f39525 1:be27ed110b50
       
     1 #============================================================================ 
       
     2 #Name        : configuration_model.py 
       
     3 #Part of     : Helium 
       
     4 
       
     5 #Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     6 #All rights reserved.
       
     7 #This component and the accompanying materials are made available
       
     8 #under the terms of the License "Eclipse Public License v1.0"
       
     9 #which accompanies this distribution, and is available
       
    10 #at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
    11 #
       
    12 #Initial Contributors:
       
    13 #Nokia Corporation - initial contribution.
       
    14 #
       
    15 #Contributors:
       
    16 #
       
    17 #Description:
       
    18 #===============================================================================
       
    19 
       
    20 import amara
       
    21 from amara import bindery
       
    22 import logging
       
    23 import types
       
    24 import copy
       
    25 
       
    26 _logger = logging.getLogger('configurationmodel')
       
    27 #logging.basicConfig(level=logging.DEBUG)
       
    28 _handler = logging.StreamHandler()
       
    29 _handler.setFormatter(logging.Formatter('%(levelname)s: %(message)s'))
       
    30 _logger.addHandler(_handler)
       
    31 
       
    32 
       
    33 class PropertyDef(object):
       
    34     """ The model definition of a property. """
       
    35     
       
    36     def __init__(self, property_node):
       
    37         """ Initialization. """
       
    38         if not hasattr(property_node, 'name'):
       
    39             raise Exception("Name is not defined for '" + str(property_node) + "'")
       
    40         if not hasattr(property_node, 'type'):
       
    41             raise Exception("Type is not defined for '" + str(property_node.name) + "'")
       
    42         if not hasattr(property_node, 'description'):
       
    43             raise Exception("Description is not defined for '" + str(property_node.name) + "'")
       
    44             
       
    45         self.name = str(property_node.name)
       
    46         self.editStatus = str(property_node.editStatus)
       
    47         self.type = str(property_node.type)
       
    48         self.description = str(property_node.description).strip()
       
    49         
       
    50         if len(self.description) == 0:
       
    51             _logger.log(logging.ERROR, "Description has no content for '" + str(property_node.name) + "'")
       
    52         
       
    53         if hasattr(property_node, 'deprecated'):
       
    54             self.deprecated = str(property_node.deprecated)
       
    55                         
       
    56     def __repr__(self):
       
    57         return self.name
       
    58         
       
    59     def __str__(self):
       
    60         return self.name
       
    61     
       
    62     
       
    63 class GroupDef(object):
       
    64     """ The model definition of a group of properties. """
       
    65     def __init__(self, group_node):
       
    66         """ Initialization. """
       
    67         self.name = str(group_node.name)
       
    68         self.description = str(group_node.description)
       
    69         self.properties = {}
       
    70         self.propref = []
       
    71         for property_ in group_node.propertyRef:
       
    72             self.properties[str(property_)] = property_.usage
       
    73             
       
    74     def check_config(self, config, items):
       
    75         """ Checks that the set of properties in a group are properly defined. """
       
    76         defined_props = [p for p in self.properties.keys() if config.has_key(p)]
       
    77         if len(defined_props) > 0:
       
    78             required_props = [p for p in self.properties.keys() if self.properties[p] == 'required']
       
    79             required_not_defined_props = set(required_props).difference(set(defined_props))
       
    80             for undefined_property in required_not_defined_props:
       
    81                 items.append(UndefinedRequiredInGroupItem((self.name, undefined_property)))
       
    82         
       
    83         
       
    84 class DataModel(object):
       
    85     """ A model of the configuration properties. """
       
    86     def __init__(self, modelpath):
       
    87         """ Initialization. """
       
    88         doc = amara.parse(open(modelpath, 'r'))
       
    89         
       
    90         self.properties = {}
       
    91         self.required_props = []
       
    92         for property_ in doc.heliumDataModel.property:
       
    93             self.properties[str(property_.name)] = PropertyDef(property_)
       
    94                    
       
    95         self.nongroupedproperties = copy.copy(self.properties)
       
    96         self.groups = {}
       
    97         for group in doc.heliumDataModel.group:
       
    98             groupobj = GroupDef(group)
       
    99             self.groups[str(group.name)] = groupobj
       
   100             
       
   101             for prop in groupobj.properties:
       
   102                 groupobj.propref.append(self.properties[prop])
       
   103                 if prop in self.nongroupedproperties:
       
   104                     del self.nongroupedproperties[prop]
       
   105                     
       
   106             groupobj.propref.sort()
       
   107             
       
   108             required_props_in_group = [p for p in group.propertyRef if p.usage == 'required']
       
   109             
       
   110             for required_prop in required_props_in_group:
       
   111                 self.required_props.append(required_prop)
       
   112                 if not self.properties.has_key(str(required_prop)):
       
   113                     raise Exception("Required property " + str(required_prop) + " is not defined!")
       
   114         
       
   115     def validate_config(self, config):
       
   116         """ Validate the Ant configuration against the model. """
       
   117         items = []
       
   118         self._check_deprecated_properties(config, items)
       
   119         self._check_undefined_properties(config, items)
       
   120         self._check_undefined_properties_in_groups(config, items)
       
   121         self._check_type_validation(config, items)
       
   122         self._check_defined_properties_not_in_groups(config, items)
       
   123         return items
       
   124     
       
   125     def validate_config_at_startup(self, config):
       
   126         """ Validate the Ant configuration against the model at build startup. """
       
   127         items = []
       
   128         
       
   129         for p in self.required_props:
       
   130             if not config.has_key(str(p)):
       
   131                 print "Required property " + str(p) + " is not defined!"
       
   132         
       
   133         return items
       
   134     
       
   135     def _check_deprecated_properties(self, config, items):
       
   136         """ Check that deprecated properties not being used. """
       
   137         deprecated_props = [p for p in self.properties.values() if hasattr(p, 'deprecated')]
       
   138         for deprecated_prop in deprecated_props:
       
   139             _logger.debug('Checking deprecated property: ' + str(deprecated_prop))
       
   140             if config.has_key(str(deprecated_prop)):
       
   141                 items.append(UsingDeprecatedItem(deprecated_prop))
       
   142     
       
   143     def _check_undefined_properties(self, config, items):
       
   144         """ Check for any defined properties that are not in the model. """ 
       
   145         undefined_properties = [p for p in config.keys() if p not in self.properties]
       
   146         undefined_properties.sort()
       
   147         for undefined_property in undefined_properties:
       
   148             items.append(MissingFromDataModelItem(undefined_property))
       
   149 
       
   150     def _check_undefined_properties_in_groups(self, config, items):
       
   151         for group in self.groups.values():
       
   152             _logger.debug('Checking group: %s' % group.name)
       
   153             group.check_config(config, items)
       
   154     
       
   155     def _check_defined_properties_not_in_groups(self, config, items):
       
   156         gp = []
       
   157         for group in self.groups.values():
       
   158             gp = gp + group.properties.keys()
       
   159         for p in self.properties.values():
       
   160             if not str(p) in gp:
       
   161                 raise Exception(str(p) + ' not in a group')
       
   162     
       
   163     def _check_type_validation(self, config, items):
       
   164         prop_string = [p for p in self.properties.values() if p.type == 'string']
       
   165         prop_integer = [p for p in self.properties.values() if p.type == 'integer']
       
   166         prop_boolean = [p for p in self.properties.values() if p.type == 'boolean']
       
   167         prop_flag = [p for p in self.properties.values() if p.type == 'flag']
       
   168         
       
   169         for prop in prop_integer:
       
   170             if config.has_key(str(prop)):
       
   171                 if not config[str(prop)].isdigit():
       
   172                     items.append(WrongTypeItem(("integer", prop)))            
       
   173                
       
   174         for prop in prop_boolean:
       
   175             if config.has_key(str(prop)) :
       
   176                 if not (config[str(prop)] == 'false' or 'true'):
       
   177                     items.append(WrongTypeItem(("boolean", prop)))
       
   178                     
       
   179         for prop in prop_string:
       
   180             if config.has_key(str(prop)):
       
   181                 if len(config[str(prop)]) == 0:
       
   182                     items.append(WrongTypeItem(("string", prop)))
       
   183 
       
   184         
       
   185 class Item(object):
       
   186     level = logging.INFO
       
   187     message = ''
       
   188 
       
   189     def __init__(self, values):
       
   190         """ Initialization. """
       
   191         self.values = values
       
   192     
       
   193     def log(self, logger):
       
   194         logger.log(self.level, str(self))
       
   195         
       
   196     def __str__(self):
       
   197         return self.message % self.values
       
   198 
       
   199 
       
   200 class MissingFromDataModelItem(Item):
       
   201     level = logging.INFO
       
   202     message = 'Property not in data model: %s'
       
   203 
       
   204     
       
   205 class UsingDeprecatedItem(Item):
       
   206     level = logging.WARNING
       
   207     message = 'Deprecated property used: %s'
       
   208 
       
   209 
       
   210 class UndefinedRequiredInGroupItem(Item):
       
   211     level = logging.WARNING
       
   212     message = 'Required property in %s group is not defined: %s'
       
   213 
       
   214     
       
   215 class WrongTypeItem(Item):
       
   216     level = logging.WARNING
       
   217     message = 'Invalid %s value: %s'