Module configuration_model |
[hide private]
[frames] | no frames]

# Source Code for Module configuration_model

      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'
    218