configurationengine/source/cone/confml/persistentconfml.py
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
child 5 d2c80f5cab53
equal deleted inserted replaced
2:87cfa131b535 3:e7e0ae78773e
    11 #
    11 #
    12 # Contributors:
    12 # Contributors:
    13 #
    13 #
    14 # Description: 
    14 # Description: 
    15 #
    15 #
       
    16 import os
    16 import re
    17 import re
    17 import logging
    18 import logging
    18 import xml.parsers.expat
       
    19 try:
    19 try:
    20     from cElementTree import ElementTree
    20     from cElementTree import ElementTree
    21 except ImportError:
    21 except ImportError:
    22     try:    
    22     try:    
    23         from elementtree import ElementTree
    23         from elementtree import ElementTree
    25         try:
    25         try:
    26             from xml.etree import cElementTree as ElementTree
    26             from xml.etree import cElementTree as ElementTree
    27         except ImportError:
    27         except ImportError:
    28             from xml.etree import ElementTree
    28             from xml.etree import ElementTree
    29 
    29 
    30 """ cone specific imports """
    30 # cone specific imports
    31 from cone.public import persistence, exceptions, api, utils, container
    31 from cone.public import persistence, exceptions, api, utils, container, parsecontext
    32 from cone.confml import model
    32 from cone.confml import model
    33 
    33 
    34 CONFIGURATION_NAMESPACES = ["http://www.s60.com/xml/confml/2","http://www.s60.com/xml/confml/1"]
    34 CONFIGURATION_NAMESPACES = ["http://www.s60.com/xml/confml/2","http://www.s60.com/xml/confml/1"]
    35 INCLUDE_NAMESPACES       = ["http://www.w3.org/2001/XInclude","http://www.w3.org/2001/xinclude"]
    35 INCLUDE_NAMESPACES       = ["http://www.w3.org/2001/XInclude","http://www.w3.org/2001/xinclude"]
    36 XLINK_NAMESPACES         = ["http://www.w3.org/1999/xlink"]
    36 XLINK_NAMESPACES         = ["http://www.w3.org/1999/xlink"]
    40 
    40 
    41 def dumps(obj, indent=True):
    41 def dumps(obj, indent=True):
    42     etree = ConfmlWriter().dumps(obj)
    42     etree = ConfmlWriter().dumps(obj)
    43     if indent:
    43     if indent:
    44         persistence.indent(etree)
    44         persistence.indent(etree)
    45     return ElementTree.tostring(etree)
    45     result = ElementTree.tostring(etree)
       
    46     
       
    47     # To make the output the same in linux and windows
       
    48     # (needed to make testing easier)
       
    49     if os.linesep != '\r\n':
       
    50         result = result.replace(os.linesep, '\r\n')
       
    51     
       
    52     return result
    46 
    53 
    47 def loads(xml):
    54 def loads(xml):
    48     return ConfmlReader().loads(xml)
    55     return ConfmlReader().loads(xml)
    49 
    56 
    50 
    57 def add_parse_warning(msg, line, type='model.confml'):
       
    58     parsecontext.get_confml_context().handle_problem(
       
    59         api.Problem(msg,
       
    60                     severity = api.Problem.SEVERITY_WARNING,
       
    61                     type     = type,
       
    62                     line     = line))
       
    63 
       
    64 def add_unknown_element_warning(elem):
       
    65     add_parse_warning("Unknown element '%s'" % elem.tag,
       
    66                       utils.etree.get_lineno(elem),
       
    67                       type='model.confml.unknown_element')
    51 
    68 
    52 class ConfmlWriter(persistence.ConeWriter):
    69 class ConfmlWriter(persistence.ConeWriter):
    53     """
    70     """
    54     """ 
    71     """ 
    55     def dumps(self, obj):
    72     def dumps(self, obj):
    67     def loads(self, xmlstr):
    84     def loads(self, xmlstr):
    68         """
    85         """
    69         @param xml: The xml which to read. reads only the first object. 
    86         @param xml: The xml which to read. reads only the first object. 
    70         """
    87         """
    71         reader = get_reader_for_elem("configuration")
    88         reader = get_reader_for_elem("configuration")
    72         etree = utils.etree.fromstring(xmlstr)
    89         try:
       
    90             etree = utils.etree.fromstring(xmlstr)
       
    91         except exceptions.XmlParseError, e:
       
    92             e.problem_type = 'xml.confml'
       
    93             raise e
    73         return reader.loads(etree)
    94         return reader.loads(etree)
    74 
    95 
    75 
    96 
    76 class ConfigurationWriter(ConfmlWriter):
    97 class ConfigurationWriter(ConfmlWriter):
    77     """
    98     """
   103             elem.set("xmlns:xi",self.include_namespace)
   124             elem.set("xmlns:xi",self.include_namespace)
   104         if self.include_namespace:
   125         if self.include_namespace:
   105             elem.set("xmlns:xlink",self.xlink_namespace)
   126             elem.set("xmlns:xlink",self.xlink_namespace)
   106         if self.schema_namespace:
   127         if self.schema_namespace:
   107             elem.set("xmlns:xs",self.schema_namespace)
   128             elem.set("xmlns:xs",self.schema_namespace)
   108         elem.set("name",obj.get_name()) 
   129         if obj.get_name():
       
   130             elem.set("name", obj.get_name()) 
       
   131         if obj.version != None:
       
   132             elem.set("version", obj.version) 
       
   133         if obj.get_id():
       
   134             elem.set('id', obj.get_id())
       
   135 
   109         for child in obj._objects():
   136         for child in obj._objects():
   110             """ Make sure that the object is mapped to an object in this model """
   137             """ Make sure that the object is mapped to an object in this model """
   111             mobj = child._get_mapper('confml').map_object(child)
   138             mobj = child._get_mapper('confml').map_object(child)
   112             writer = get_writer_for_class(mobj.__class__.__name__)
   139             writer = get_writer_for_class(mobj.__class__.__name__)
   113             childelem = writer.dumps(child)
   140             childelem = writer.dumps(child)
   135         self.configuration_namespaces  = CONFIGURATION_NAMESPACES
   162         self.configuration_namespaces  = CONFIGURATION_NAMESPACES
   136         self.include_namespaces        = INCLUDE_NAMESPACES
   163         self.include_namespaces        = INCLUDE_NAMESPACES
   137         self.schema_namespaces         = SCHEMA_NAMESPACES
   164         self.schema_namespaces         = SCHEMA_NAMESPACES
   138 
   165 
   139     def loads(self, etree):
   166     def loads(self, etree):
   140         configuration = model.ConfmlConfiguration("")
   167         configuration = model.ConfmlConfiguration(name=etree.get("name"),
   141         configuration.set_name(etree.get("name") or 'unknown') 
   168                                                   id=etree.get("id"),
       
   169                                                   version=etree.get("version"))
       
   170         configuration.lineno = utils.etree.get_lineno(etree)
       
   171         # configuration.set_name(etree.get("name") or 'unknown') 
   142         configuration.set_ref(etree.get("name") or 'unknown')
   172         configuration.set_ref(etree.get("name") or 'unknown')
   143         for elem in etree.getchildren():
   173         for elem in etree.getchildren():
   144             # At the moment we ignore the namespace of elements
   174             # At the moment we ignore the namespace of elements
   145             (namespace,elemname) = get_elemname(elem.tag)
   175             (namespace,elemname) = get_elemname(elem.tag)
   146             try:
   176             try:
   147                 reader = get_reader_for_elem(elemname)
   177                 reader = get_reader_for_elem(elemname)
   148                 obj = reader.loads(elem)
   178                 obj = reader.loads(elem)
   149                 if obj:
   179                 if obj:
   150                     configuration.add(obj)
   180                     configuration.add(obj)
   151             except exceptions.ConePersistenceError,e:
   181             except exceptions.ConePersistenceError,e:
   152                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
   182                 add_unknown_element_warning(elem)
   153                 continue
   183                 continue
   154         return configuration
   184         return configuration
   155 
   185 
   156 
   186 
   157 class MetaWriter(ConfmlWriter):
   187 class MetaWriter(ConfmlWriter):
   200         else:
   230         else:
   201             return False
   231             return False
   202 
   232 
   203     def loads(self,etree):
   233     def loads(self,etree):
   204         metaelem = model.ConfmlMeta()
   234         metaelem = model.ConfmlMeta()
       
   235         metaelem.lineno = utils.etree.get_lineno(etree)
   205         for elem in etree.getchildren():            
   236         for elem in etree.getchildren():            
   206             (namespace,elemname) = get_elemname(elem.tag)
   237             (namespace,elemname) = get_elemname(elem.tag)
   207             attributes = {}
   238             attributes = {}
   208             for key in elem.keys():
   239             for key in elem.keys():
   209                 attributes[key] = elem.get(key)
   240                 attributes[key] = elem.get(key)
   248         else:
   279         else:
   249             return False
   280             return False
   250 
   281 
   251     def loads(self,elem):
   282     def loads(self,elem):
   252         desc = model.ConfmlDescription(elem.text)
   283         desc = model.ConfmlDescription(elem.text)
       
   284         desc.lineno = utils.etree.get_lineno(elem)
   253         return desc
   285         return desc
   254 
   286 
   255 class ConfigurationProxyWriter(ConfmlWriter):
   287 class ConfigurationProxyWriter(ConfmlWriter):
   256     """
   288     """
   257     """ 
   289     """ 
   293 
   325 
   294     def loads(self, elem):
   326     def loads(self, elem):
   295         """
   327         """
   296         @param elem: The xml include elem
   328         @param elem: The xml include elem
   297         """
   329         """
   298         
   330         proxy = api.ConfigurationProxy(self.parse_include(elem))
   299         return api.ConfigurationProxy(self.parse_include(elem))
   331         # proxy.lineno = utils.etree.get_lineno(elem)
       
   332         return proxy
   300 
   333 
   301     def parse_include(self,include):
   334     def parse_include(self,include):
   302         #print "Found include %s" % include.get('href').replace('#/','')
   335         #print "Found include %s" % include.get('href').replace('#/','')
   303         return include.get('href').replace('#/','')
   336         return include.get('href').replace('#/','')
   304 
   337 
   319     def dumps(self, obj):
   352     def dumps(self, obj):
   320         """
   353         """
   321         @param obj: The Configuration object 
   354         @param obj: The Configuration object 
   322         """
   355         """
   323         elem = ElementTree.Element('feature', 
   356         elem = ElementTree.Element('feature', 
   324                                    {'ref' : obj.get_ref(),
   357                                    {'ref' : obj.get_ref()})
   325                                     'name' : obj.get_name()})
   358         if obj.get_name():
       
   359             elem.set('name', obj.get_name())
   326         if obj.get_type():
   360         if obj.get_type():
   327             elem.set('type', obj.get_type())
   361             elem.set('type', obj.get_type())
       
   362         if obj.get_id() != None:
       
   363             elem.set('id', obj.get_id())
       
   364         if obj.get_relevant() != None:
       
   365             elem.set('relevant', obj.get_relevant())
       
   366         if obj.get_constraint() != None:
       
   367             elem.set('constraint', obj.get_constraint())
   328         for child in obj._objects():
   368         for child in obj._objects():
   329             """ Make sure that the object is mapped to an object in this model """
   369             """ Make sure that the object is mapped to an object in this model """
   330             mobj = child._get_mapper('confml').map_object(child)
   370             mobj = child._get_mapper('confml').map_object(child)
   331             writer = get_writer_for_class(mobj.__class__.__name__)
   371             writer = get_writer_for_class(mobj.__class__.__name__)
   332             childelem = writer.dumps(child)
   372             childelem = writer.dumps(child)
   358             feature = api.FeatureSequence(elem.get('ref'))
   398             feature = api.FeatureSequence(elem.get('ref'))
   359         else:
   399         else:
   360             feature = model.ConfmlFeature(elem.get('ref'))
   400             feature = model.ConfmlFeature(elem.get('ref'))
   361         if elem.get('name'):
   401         if elem.get('name'):
   362             feature.set_name(elem.get('name'))
   402             feature.set_name(elem.get('name'))
       
   403         if elem.get('id') != None:
       
   404             feature.set_id(elem.get('id'))
       
   405         if elem.get('relevant') != None:
       
   406             feature.set_relevant(elem.get('relevant'))
       
   407         if elem.get('constraint') != None:
       
   408             feature.set_constraint(elem.get('constraint'))
   363         feature.set_type(type)
   409         feature.set_type(type)
       
   410         feature.lineno = utils.etree.get_lineno(elem)
   364         for elem in elem.getchildren():
   411         for elem in elem.getchildren():
   365             # At the moment we ignore the namespace of elements
   412             # At the moment we ignore the namespace of elements
   366             (namespace,elemname) = get_elemname(elem.tag)
   413             (namespace,elemname) = get_elemname(elem.tag)
   367             try:
   414             try:
   368                 reader = get_reader_for_elem(elemname)
   415                 reader = get_reader_for_elem(elemname)
   369                 obj = reader.loads(elem)
   416                 obj = reader.loads(elem)
   370                 feature.add(obj)
   417                 feature.add(obj)
   371             except exceptions.ConePersistenceError,e:
   418             except exceptions.ConePersistenceError,e:
   372                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
   419                 add_unknown_element_warning(elem)
   373                 continue
   420                 continue
   374         return feature
   421         return feature
   375 
   422 
   376 
   423 
   377 class OptionWriter(ConfmlWriter):
   424 class OptionWriter(ConfmlWriter):
   394         objdict = {}
   441         objdict = {}
   395         if obj.get_name() is not None: objdict['name'] = obj.get_name()
   442         if obj.get_name() is not None: objdict['name'] = obj.get_name()
   396         if obj.get_value() is not None: objdict['value'] = obj.get_value()
   443         if obj.get_value() is not None: objdict['value'] = obj.get_value()
   397         if obj.map is not None: objdict['map'] = obj.map
   444         if obj.map is not None: objdict['map'] = obj.map
   398         if obj.relevant is not None: objdict['relevant'] = obj.relevant
   445         if obj.relevant is not None: objdict['relevant'] = obj.relevant
       
   446         if obj.display_name is not None: objdict['displayName'] = obj.display_name
       
   447         if obj.map_value is not None: objdict['mapValue'] = obj.map_value
       
   448 
   399         elem = ElementTree.Element('option', objdict)
   449         elem = ElementTree.Element('option', objdict)
   400         
   450         
   401         return elem
   451         return elem
   402 
   452 
   403 
   453 
   420         @param elem: The xml include elem
   470         @param elem: The xml include elem
   421         """
   471         """
   422         name = elem.get('name')
   472         name = elem.get('name')
   423         value = elem.get('value')
   473         value = elem.get('value')
   424         optmap = elem.get('map')
   474         optmap = elem.get('map')
       
   475 
   425         if value == None and optmap == None:
   476         if value == None and optmap == None:
   426             logging.getLogger('cone').warning("Encountered option with no value")
   477             logging.getLogger('cone').warning("Encountered option with no value")
   427             option = None
   478             option = None
   428         else:
   479         else:
   429             option = api.Option(name, value, map=optmap, relevant=elem.get('relevant'))
   480             option = api.Option(name, value, map=optmap, 
       
   481                                 relevant=elem.get('relevant'),
       
   482                                 map_value=elem.get('mapValue'), 
       
   483                                 display_name=elem.get('displayName'))
       
   484             option.lineno = utils.etree.get_lineno(elem) 
   430         return option
   485         return option
   431 
   486 
   432 
   487 
   433 class IconWriter(ConfmlWriter):
   488 class IconWriter(ConfmlWriter):
   434     @classmethod
   489     @classmethod
   469         """
   524         """
   470         @param elem: The xml include elem
   525         @param elem: The xml include elem
   471         """
   526         """
   472         href = elem.get('{%s}href' % XLINK_NAMESPACES[0])
   527         href = elem.get('{%s}href' % XLINK_NAMESPACES[0])
   473         obj = model.ConfmlIcon(href)
   528         obj = model.ConfmlIcon(href)
       
   529         obj.lineno = utils.etree.get_lineno(elem)
   474         return obj
   530         return obj
   475 
   531 
   476 
   532 
   477 class PropertyWriter(ConfmlWriter):
   533 class PropertyWriter(ConfmlWriter):
   478     @classmethod
   534     @classmethod
   479     def supported_class(cls, classname):
   535     def supported_class(cls, classname):
   480         """
   536         """
   481         Class method to determine if this ConfmlWriter supports writing
   537         Class method to determine if this ConfmlWriter supports writing
   482         of the given class name
   538         of the given class name
   483         """
   539         """
   484         if classname=="ConfmlProperty":
   540         if classname=="Property":
   485             return True
   541             return True
   486         else:
   542         else:
   487             return False
   543             return False
   488 
   544 
   489     def dumps(self, obj):
   545     def dumps(self, obj):
   516 
   572 
   517     def loads(self, elem):
   573     def loads(self, elem):
   518         """
   574         """
   519         @param elem: The xml include elem
   575         @param elem: The xml include elem
   520         """
   576         """
   521         option = model.ConfmlProperty(name=elem.get('name'),value=elem.get('value'), unit=elem.get('unit'))
   577         option = api.Property(name=elem.get('name'),value=elem.get('value'), unit=elem.get('unit'))
       
   578         option.lineno = utils.etree.get_lineno(elem)
   522         return option
   579         return option
   523 
   580 
   524 
   581 
   525 class XmlSchemaFacetWriter(ConfmlWriter):
   582 class XmlSchemaFacetWriter(ConfmlWriter):
   526     MAPPING = {'ConfmlLength'       : 'xs:length',
   583     MAPPING = {'ConfmlLength'       : 'xs:length',
   572         @param elem: The XML schema facet element
   629         @param elem: The XML schema facet element
   573         """
   630         """
   574         elem_name = utils.xml.split_tag_namespace(elem.tag)[1]
   631         elem_name = utils.xml.split_tag_namespace(elem.tag)[1]
   575         facet_class = self.MAPPING[elem_name]
   632         facet_class = self.MAPPING[elem_name]
   576         obj = facet_class(elem.get('value'))
   633         obj = facet_class(elem.get('value'))
       
   634         obj.lineno = utils.etree.get_lineno(elem)
   577         return obj
   635         return obj
   578 
   636 
   579 
   637 
   580 class DataWriter(ConfmlWriter):
   638 class DataWriter(ConfmlWriter):
   581     @classmethod
   639     @classmethod
   582     def supported_class(cls, classname):
   640     def supported_class(cls, classname):
   583         """
   641         """
   584         Class method to determine if this ConfmlWriter supports writing
   642         Class method to determine if this ConfmlWriter supports writing
   585         of the given class name
   643         of the given class name
   586         """
   644         """
   587         if classname=="Data":
   645         if classname=="Data" or \
   588             return True
   646            classname=="DataContainer":
   589         if classname=="DataContainer":
       
   590             return True
   647             return True
   591         else:
   648         else:
   592             return False
   649             return False
   593 
   650 
   594     def dumps(self, obj):
   651     def dumps(self, obj):
   595         """
   652         """
   596         @param obj: The Data object 
   653         @param obj: The Data object 
   597         """
   654         """
   598         # Create a data hierarchy of the 
   655         # Create a data hierarchy of the 
   599         elem = ElementTree.Element(obj.get_ref())
   656         elem = ElementTree.Element(obj.get_ref())
   600         if hasattr(obj,'get_value') and obj.get_value() and not obj.get_map():
   657         if hasattr(obj,'get_map') and obj.get_map() is not None:
       
   658             elem.set('map', obj.get_map())
       
   659         elif hasattr(obj,'get_value') and obj.get_value() is not None:
   601             elem.text = obj.get_value()
   660             elem.text = obj.get_value()
   602         elif hasattr(obj,'get_map') and obj.get_map():
       
   603             elem.set('map', obj.get_map())
       
   604         if hasattr(obj,'template') and obj.template == True:
   661         if hasattr(obj,'template') and obj.template == True:
   605             elem.set('template','true')
   662             elem.set('template','true')
   606         if hasattr(obj,'policy') and obj.policy != '':
   663         if hasattr(obj,'policy') and obj.policy != '':
   607             elem.set('extensionPolicy',obj.policy)
   664             elem.set('extensionPolicy',obj.policy)
       
   665         if hasattr(obj,'empty') and obj.empty == True:
       
   666             elem.set('empty','true')
   608         for child in obj._objects():
   667         for child in obj._objects():
   609             writer = DataWriter()
   668             writer = DataWriter()
   610             childelem = writer.dumps(child)
   669             childelem = writer.dumps(child)
   611             if childelem != None:
   670             if childelem != None:
   612                 elem.append(childelem)
   671                 elem.append(childelem)
   632         @param elem: The xml include elem
   691         @param elem: The xml include elem
   633         """
   692         """
   634         
   693         
   635         (namespace,elemname) = get_elemname(elem.tag)
   694         (namespace,elemname) = get_elemname(elem.tag)
   636         obj = api.DataContainer(elemname, container=True)
   695         obj = api.DataContainer(elemname, container=True)
       
   696         obj.lineno = utils.etree.get_lineno(elem)
   637         for elem in elem.getchildren():
   697         for elem in elem.getchildren():
   638             try:
   698             try:
   639                 reader = ElemReader(attr='data')
   699                 reader = ElemReader(attr='data')
   640                 childobj = reader.loads(elem)
   700                 childobj = reader.loads(elem)
   641                 obj.add(childobj)
   701                 obj.add(childobj)
   642             except exceptions.ConePersistenceError,e:
   702             except exceptions.ConePersistenceError,e:
   643                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
   703                 add_unknown_element_warning(elem)
   644                 continue
   704                 continue
   645         return obj
   705         return obj
   646 
   706 
   647 
   707 
   648 class ViewWriter(ConfmlWriter):
   708 class ViewWriter(ConfmlWriter):
   661     def dumps(self, obj):
   721     def dumps(self, obj):
   662         """
   722         """
   663         @param obj: The Configuration object 
   723         @param obj: The Configuration object 
   664         """
   724         """
   665         elem = ElementTree.Element('view', 
   725         elem = ElementTree.Element('view', 
   666                                    {'id' : obj.get_ref(),
   726                                    {'name' : obj.get_name()})
   667                                     'name' : obj.get_name()})
   727         if obj.id != None:  
       
   728             elem.set('id', obj.id)
   668         for child in obj._objects():
   729         for child in obj._objects():
   669             """ Make sure that the object is mapped to an object in this model """
   730             """ Make sure that the object is mapped to an object in this model """
   670             mobj = child._get_mapper('confml').map_object(child)
   731             mobj = child._get_mapper('confml').map_object(child)
   671             writer = get_writer_for_class(mobj.__class__.__name__)
   732             writer = get_writer_for_class(mobj.__class__.__name__)
   672             childelem = writer.dumps(child)
   733             childelem = writer.dumps(child)
   694         @param elem: The xml include elem
   755         @param elem: The xml include elem
   695         """
   756         """
   696         vid = elem.get('id')
   757         vid = elem.get('id')
   697         name = elem.get('name')
   758         name = elem.get('name')
   698         view = model.ConfmlView(name, id=vid)
   759         view = model.ConfmlView(name, id=vid)
       
   760         view.lineno = utils.etree.get_lineno(elem)
   699         for elem in elem.getchildren():
   761         for elem in elem.getchildren():
   700             # At the moment we ignore the namespace of elements
   762             # At the moment we ignore the namespace of elements
   701             (namespace,elemname) = get_elemname(elem.tag)
   763             (namespace,elemname) = get_elemname(elem.tag)
   702             try:
   764             try:
   703                 reader = get_reader_for_elem(elemname)
   765                 reader = get_reader_for_elem(elemname)
   704                 obj = reader.loads(elem)
   766                 obj = reader.loads(elem)
   705                 view.add(obj)
   767                 view.add(obj)
   706             except exceptions.ConePersistenceError,e:
   768             except exceptions.ConePersistenceError,e:
   707                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
   769                 add_unknown_element_warning(elem)
   708                 continue
   770                 continue
   709         return view
   771         return view
   710 
   772 
   711 
   773 
   712 class GroupWriter(ConfmlWriter):
   774 class GroupWriter(ConfmlWriter):
   725         """
   787         """
   726         @param obj: The Configuration object 
   788         @param obj: The Configuration object 
   727         """
   789         """
   728         elem = ElementTree.Element('group', 
   790         elem = ElementTree.Element('group', 
   729                                    {'name' : obj.get_name()})
   791                                    {'name' : obj.get_name()})
       
   792         if obj.get_id():
       
   793             elem.set('id', obj.get_id())
       
   794 
   730         for child in obj._objects():
   795         for child in obj._objects():
   731             """ Make sure that the object is mapped to an object in this model """
   796             """ Make sure that the object is mapped to an object in this model """
   732             mobj = child._get_mapper('confml').map_object(child)
   797             mobj = child._get_mapper('confml').map_object(child)
   733             writer = get_writer_for_class(mobj.__class__.__name__)
   798             writer = get_writer_for_class(mobj.__class__.__name__)
   734             childelem = writer.dumps(child)
   799             childelem = writer.dumps(child)
   756         @param elem: The xml include elem
   821         @param elem: The xml include elem
   757         """
   822         """
   758         gname = elem.get('name')
   823         gname = elem.get('name')
   759         gref = utils.resourceref.to_dref(gname).replace('.','_')
   824         gref = utils.resourceref.to_dref(gname).replace('.','_')
   760         group = model.ConfmlGroup(gref, name=gname)
   825         group = model.ConfmlGroup(gref, name=gname)
       
   826         group.lineno = utils.etree.get_lineno(elem)
       
   827         if elem.get('id'):
       
   828             group.set_id(elem.get('id'))
   761         for elem in elem.getchildren():
   829         for elem in elem.getchildren():
   762             # At the moment we ignore the namespace of elements
   830             # At the moment we ignore the namespace of elements
   763             (namespace,elemname) = get_elemname(elem.tag)
   831             (namespace,elemname) = get_elemname(elem.tag)
   764             try:
   832             try:
   765                 reader = get_reader_for_elem(elemname, 'group')
   833                 reader = get_reader_for_elem(elemname, 'group')
   766                 obj = reader.loads(elem)
   834                 obj = reader.loads(elem)
   767                 if obj != None:
   835                 if obj != None:
   768                     group.add(obj)
   836                     group.add(obj)
   769             except exceptions.ConePersistenceError,e:
   837             except exceptions.ConePersistenceError,e:
   770                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
   838                 add_unknown_element_warning(elem)
   771                 continue
   839                 continue
   772         return group
   840         return group
   773 
       
   774 
       
   775 class GroupSettingWriter(ConfmlWriter):
       
   776     """
       
   777     """ 
       
   778     @classmethod
       
   779     def supported_class(cls, classname):
       
   780         """
       
   781         Class method to determine if this ConfmlWriter supports writing
       
   782         of the given class name
       
   783         """
       
   784         if classname=="FeatureLink":
       
   785             return True
       
   786         else:
       
   787             return False
       
   788 
       
   789     def dumps(self, obj):
       
   790         """
       
   791         @param obj: The Configuration object 
       
   792         """
       
   793         ref = obj.fqr.replace('.','/')
       
   794         elem = ElementTree.Element('setting', 
       
   795                                    {'ref' : ref})
       
   796         return elem
       
   797 
       
   798 class GroupSettingReader(ConfmlReader):
       
   799     """
       
   800     """ 
       
   801     @classmethod
       
   802     def supported_elem(cls, elemname, parent=None):
       
   803         """
       
   804         Class method to determine if this ConfmlWriter supports reading
       
   805         of the given elem name
       
   806         """
       
   807         if elemname=='setting' and parent=='group':
       
   808             return True
       
   809         else:
       
   810             return False
       
   811 
       
   812     def loads(self, elem):
       
   813         """
       
   814         @param elem: The xml include elem
       
   815         """
       
   816         ref = elem.get('ref') or ''
       
   817         ref = ref.replace('/','.')
       
   818         return api.FeatureLink(ref)
       
   819 
       
   820 
   841 
   821 
   842 
   822 class ConfmlSettingWriter(ConfmlWriter):
   843 class ConfmlSettingWriter(ConfmlWriter):
   823     @classmethod
   844     @classmethod
   824     def supported_class(cls, classname):
   845     def supported_class(cls, classname):
   835            classname=="ConfmlMultiSelectionSetting" or \
   856            classname=="ConfmlMultiSelectionSetting" or \
   836            classname=="ConfmlDateSetting" or \
   857            classname=="ConfmlDateSetting" or \
   837            classname=="ConfmlTimeSetting" or \
   858            classname=="ConfmlTimeSetting" or \
   838            classname=="ConfmlDateTimeSetting" or \
   859            classname=="ConfmlDateTimeSetting" or \
   839            classname=="ConfmlDurationSetting" or \
   860            classname=="ConfmlDurationSetting" or \
       
   861            classname=="ConfmlHexBinarySetting" or \
   840            classname=="ConfmlFileSetting" or \
   862            classname=="ConfmlFileSetting" or \
   841            classname=="ConfmlFolderSetting" or \
   863            classname=="ConfmlFolderSetting" or \
   842            classname=="FeatureSequence" or \
   864            classname=="FeatureSequence" or \
   843            classname=="ConfmlSequenceSetting":
   865            classname=="ConfmlSequenceSetting":
   844             return True
   866             return True
   848     def dumps(self, obj):
   870     def dumps(self, obj):
   849         """
   871         """
   850         @param obj: The Configuration object 
   872         @param obj: The Configuration object 
   851         """
   873         """
   852         elem = ElementTree.Element('setting', 
   874         elem = ElementTree.Element('setting', 
   853                                    {'ref' : obj.get_ref(),
   875                                    {'ref' : obj.get_ref()})
   854                                     'name' : obj.get_name()})
   876         self._set_setting_properties(elem, obj)
       
   877         return elem
       
   878 
       
   879     def _set_setting_properties(self, elem, obj):
       
   880         """
       
   881         Set the setting properties for the given elm from the given feature object
       
   882         """
       
   883         if obj.get_name():
       
   884             elem.set('name', obj.get_name())
   855         if obj.type:
   885         if obj.type:
   856             elem.set('type', obj.get_type())
   886             elem.set('type', obj.get_type())
       
   887         if obj.get_id():
       
   888             elem.set('id', obj.get_id())
   857         if hasattr(obj,'minOccurs'):
   889         if hasattr(obj,'minOccurs'):
   858             elem.set('minOccurs', str(obj.minOccurs))
   890             elem.set('minOccurs', str(obj.minOccurs))
   859         if hasattr(obj,'maxOccurs'):
   891         if hasattr(obj,'maxOccurs'):
   860             elem.set('maxOccurs', str(obj.maxOccurs))
   892             elem.set('maxOccurs', str(obj.maxOccurs))
   861         if hasattr(obj,'readOnly') and obj.readOnly != None:
   893         if hasattr(obj,'readOnly') and obj.readOnly != None:
   868             elem.set('relevant', obj.relevant)
   900             elem.set('relevant', obj.relevant)
   869         if hasattr(obj,'mapKey') and obj.mapKey is not None:
   901         if hasattr(obj,'mapKey') and obj.mapKey is not None:
   870             elem.set('mapKey', str(obj.mapKey))
   902             elem.set('mapKey', str(obj.mapKey))
   871         if hasattr(obj,'mapValue') and obj.mapValue is not None:
   903         if hasattr(obj,'mapValue') and obj.mapValue is not None:
   872             elem.set('mapValue', str(obj.mapValue))
   904             elem.set('mapValue', str(obj.mapValue))
       
   905         if hasattr(obj,'displayName') and obj.displayName is not None:
       
   906             elem.set('displayName', str(obj.displayName))
   873             
   907             
   874         for child in obj._objects():
   908         for child in obj._objects():
   875             """ Make sure that the object is mapped to an object in this model """
   909             """ Make sure that the object is mapped to an object in this model """
   876             mobj = child._get_mapper('confml').map_object(child)
   910             mobj = child._get_mapper('confml').map_object(child)
   877             writer = get_writer_for_class(mobj.__class__.__name__)
   911             writer = get_writer_for_class(mobj.__class__.__name__)
   878             childelem = writer.dumps(child)
   912             childelem = writer.dumps(child)
   879             if childelem != None:
   913             if childelem != None:
   880                 elem.append(childelem)
   914                 elem.append(childelem)
   881         return elem
       
   882 
   915 
   883 
   916 
   884 class ConfmlSettingReader(ConfmlReader):
   917 class ConfmlSettingReader(ConfmlReader):
   885     """
   918     """
   886     """ 
   919     """ 
   889         """
   922         """
   890         Class method to determine if this ConfmlWriter supports reading
   923         Class method to determine if this ConfmlWriter supports reading
   891         of the given elem name
   924         of the given elem name
   892         """
   925         """
   893         if parent and not (parent=='feature' or parent=='setting'):
   926         if parent and not (parent=='feature' or parent=='setting'):
   894              return False
   927             return False
   895         if elemname=='setting':
   928         if elemname=='setting':
   896             return True
   929             return True
   897         else:
   930         else:
   898             return False
   931             return False
   899 
   932 
   903         """
   936         """
   904         typedef = elem.get('type')
   937         typedef = elem.get('type')
   905         if typedef == 'sequence':
   938         if typedef == 'sequence':
   906             map_key = elem.get('mapKey')
   939             map_key = elem.get('mapKey')
   907             map_value = elem.get('mapValue')
   940             map_value = elem.get('mapValue')
   908             feature = model.ConfmlSequenceSetting(elem.get('ref'), mapKey=map_key, mapValue=map_value)
   941             display_name = elem.get('displayName')
       
   942             feature = model.ConfmlSequenceSetting(elem.get('ref'), mapKey=map_key, mapValue=map_value, displayName=display_name)
   909         elif typedef == 'int':
   943         elif typedef == 'int':
   910             feature = model.ConfmlIntSetting(elem.get('ref'))
   944             feature = model.ConfmlIntSetting(elem.get('ref'))
   911         elif typedef == 'boolean':
   945         elif typedef == 'boolean':
   912             feature = model.ConfmlBooleanSetting(elem.get('ref'))
   946             feature = model.ConfmlBooleanSetting(elem.get('ref'))
   913         elif typedef == 'selection':
   947         elif typedef == 'selection':
   928             feature = model.ConfmlTimeSetting(elem.get('ref'))
   962             feature = model.ConfmlTimeSetting(elem.get('ref'))
   929         elif typedef == 'dateTime':
   963         elif typedef == 'dateTime':
   930             feature = model.ConfmlDateTimeSetting(elem.get('ref'))
   964             feature = model.ConfmlDateTimeSetting(elem.get('ref'))
   931         elif typedef == 'duration':
   965         elif typedef == 'duration':
   932             feature = model.ConfmlDurationSetting(elem.get('ref'))
   966             feature = model.ConfmlDurationSetting(elem.get('ref'))
       
   967         elif typedef == 'hexBinary':
       
   968             feature = model.ConfmlHexBinarySetting(elem.get('ref'))
   933         
   969         
   934            
   970            
   935         else:
   971         else:
   936             # Handle the default setting as int type
   972             # Handle the default setting as int type
   937             feature = model.ConfmlSetting(elem.get('ref'), type=None)
   973             feature = model.ConfmlSetting(elem.get('ref'), type=typedef)
       
   974         feature.lineno = utils.etree.get_lineno(elem)
       
   975         self._get_setting_properties(elem, feature)
       
   976         return feature
   938         
   977         
       
   978     def _get_setting_properties(self, elem, feature):
       
   979         """
       
   980         Get the setting properties for the given feature from the given xml elem
       
   981         """
   939         if elem.get('name'):
   982         if elem.get('name'):
   940             feature.set_name(elem.get('name'))
   983             feature.set_name(elem.get('name'))
       
   984         if elem.get('id'):
       
   985             feature.set_id(elem.get('id'))
   941         if elem.get('minOccurs'):
   986         if elem.get('minOccurs'):
   942             feature.minOccurs = int(elem.get('minOccurs'))
   987             feature.minOccurs = int(elem.get('minOccurs'))
   943         if elem.get('maxOccurs'):
   988         if elem.get('maxOccurs'):
   944             feature.maxOccurs = int(elem.get('maxOccurs'))
   989             feature.maxOccurs = int(elem.get('maxOccurs'))
   945         if elem.get('readOnly'):
   990         if elem.get('readOnly'):
   958                 reader = get_reader_for_elem(elemname)
  1003                 reader = get_reader_for_elem(elemname)
   959                 obj = reader.loads(elem)
  1004                 obj = reader.loads(elem)
   960                 if obj != None:
  1005                 if obj != None:
   961                     feature.add(obj,container.APPEND)
  1006                     feature.add(obj,container.APPEND)
   962                 else:
  1007                 else:
   963                     logging.getLogger('cone').warning("Invalid child %s in %s" % (elem,feature.name))
  1008                     add_parse_warning("Invalid child %s in %s" % (elem, feature.name),
       
  1009                                       utils.etree.get_lineno(elem))
   964             except exceptions.ConePersistenceError,e:
  1010             except exceptions.ConePersistenceError,e:
   965                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
  1011                 add_unknown_element_warning(elem)
   966                 continue
  1012                 continue
   967         return feature
  1013 
   968 
  1014 
       
  1015 class GroupSettingWriter(ConfmlSettingWriter):
       
  1016     """
       
  1017     """ 
       
  1018     @classmethod
       
  1019     def supported_class(cls, classname):
       
  1020         """
       
  1021         Class method to determine if this ConfmlWriter supports writing
       
  1022         of the given class name
       
  1023         """
       
  1024         if classname=="FeatureLink" or \
       
  1025            classname=="ConfmlFeatureLink":
       
  1026             return True
       
  1027         else:
       
  1028             return False
       
  1029 
       
  1030     def dumps(self, obj):
       
  1031         """
       
  1032         @param obj: The Configuration object 
       
  1033         """
       
  1034         ref = obj.fqr.replace('.','/')
       
  1035         elem = ElementTree.Element('setting', 
       
  1036                                    {'ref' : ref})
       
  1037         self._set_setting_properties(elem, obj)
       
  1038         return elem
       
  1039 
       
  1040 
       
  1041 class GroupSettingReader(ConfmlSettingReader):
       
  1042     """
       
  1043     """ 
       
  1044     @classmethod
       
  1045     def supported_elem(cls, elemname, parent=None):
       
  1046         """
       
  1047         Class method to determine if this ConfmlWriter supports reading
       
  1048         of the given elem name
       
  1049         """
       
  1050         if elemname=='setting' and parent=='group':
       
  1051             return True
       
  1052         else:
       
  1053             return False
       
  1054 
       
  1055     def loads(self, elem):
       
  1056         """
       
  1057         @param elem: The xml include elem
       
  1058         """
       
  1059         ref = elem.get('ref') or ''
       
  1060         ref = ref.replace('/','.')
       
  1061         feature_link = model.ConfmlFeatureLink(ref)
       
  1062         feature_link.lineno = utils.etree.get_lineno(elem)
       
  1063         self._get_setting_properties(elem, feature_link)
       
  1064         return feature_link
   969 
  1065 
   970 class ConfmlLocalPathWriter(ConfmlWriter):
  1066 class ConfmlLocalPathWriter(ConfmlWriter):
   971     @classmethod
  1067     @classmethod
   972     def supported_class(cls, classname):
  1068     def supported_class(cls, classname):
   973         """
  1069         """
  1005 
  1101 
  1006     def loads(self, elem):
  1102     def loads(self, elem):
  1007         """
  1103         """
  1008         @param elem: The xml include elem
  1104         @param elem: The xml include elem
  1009         """
  1105         """
  1010         return model.ConfmlLocalPath(readOnly=elem.get('readOnly'))
  1106         obj = model.ConfmlLocalPath(readOnly=elem.get('readOnly'))
       
  1107         obj.lineno = utils.etree.get_lineno(elem)
       
  1108         return obj
  1011 
  1109 
  1012 
  1110 
  1013 class ConfmlTargetPathWriter(ConfmlWriter):
  1111 class ConfmlTargetPathWriter(ConfmlWriter):
  1014     @classmethod
  1112     @classmethod
  1015     def supported_class(cls, classname):
  1113     def supported_class(cls, classname):
  1048 
  1146 
  1049     def loads(self, elem):
  1147     def loads(self, elem):
  1050         """
  1148         """
  1051         @param elem: The xml include elem
  1149         @param elem: The xml include elem
  1052         """
  1150         """
  1053         return model.ConfmlTargetPath(readOnly=elem.get('readOnly'))
  1151         obj = model.ConfmlTargetPath(readOnly=elem.get('readOnly'))
       
  1152         obj.lineno = utils.etree.get_lineno(elem)
       
  1153         return obj
  1054 
  1154 
  1055 
  1155 
  1056 class DummyWriter(ConfmlWriter):
  1156 class DummyWriter(ConfmlWriter):
  1057     """
  1157     """
  1058     Dummy writer is executed on ConE model elements that are not supposed to go to the confml file
  1158     Dummy writer is executed on ConE model elements that are not supposed to go to the confml file
  1092         @param elem: The xml include elem
  1192         @param elem: The xml include elem
  1093         """
  1193         """
  1094         
  1194         
  1095         (namespace,elemname) = get_elemname(elem.tag)
  1195         (namespace,elemname) = get_elemname(elem.tag)
  1096         obj = api.DataContainer(elemname, container=True)
  1196         obj = api.DataContainer(elemname, container=True)
       
  1197         obj.lineno = utils.etree.get_lineno(elem)
  1097         for elem in elem.getchildren():
  1198         for elem in elem.getchildren():
  1098             try:
  1199             try:
  1099                 reader = ElemReader(attr='rfs')
  1200                 reader = ElemReader(attr='rfs')
  1100                 childobj = reader.loads(elem)
  1201                 childobj = reader.loads(elem)
  1101                 obj.add(childobj)
  1202                 obj.add(childobj)
  1102             except exceptions.ConePersistenceError,e:
  1203             except exceptions.ConePersistenceError,e:
  1103                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
  1204                 add_unknown_element_warning(elem)
  1104                 continue
  1205                 continue
  1105         return obj
  1206         return obj
  1106 
  1207 
  1107 class ElemReader(ConfmlReader):
  1208 class ElemReader(ConfmlReader):
  1108     def __init__(self, **kwargs):
  1209     def __init__(self, **kwargs):
  1116         """
  1217         """
  1117         (namespace,elemname) = get_elemname(elem.tag)
  1218         (namespace,elemname) = get_elemname(elem.tag)
  1118         datavalue = None
  1219         datavalue = None
  1119         if len(list(elem)) == 0:
  1220         if len(list(elem)) == 0:
  1120             datavalue = elem.text
  1221             datavalue = elem.text
  1121         datatemplate = elem.get('template') == 'true' or self.template
  1222         obj = model.ConfmlData(
  1122         dataextensionpolicy = elem.get('extensionPolicy') or ''
  1223             ref      = elemname,
  1123         datamap = elem.get('map')
  1224             value    = datavalue,
  1124         obj = api.Data(ref=elemname,value=datavalue, template=datatemplate, attr=self.attr,policy=dataextensionpolicy,map=datamap)
  1225             template = elem.get('template') == 'true' or self.template,
       
  1226             attr     = self.attr,
       
  1227             policy   = elem.get('extensionPolicy') or '',
       
  1228             map      = elem.get('map'),
       
  1229             empty    = elem.get('empty') == 'true')
       
  1230         obj.lineno = utils.etree.get_lineno(elem)
  1125         for elem in elem.getchildren():
  1231         for elem in elem.getchildren():
  1126             try:
  1232             try:
  1127                 reader = ElemReader(**self.args)
  1233                 reader = ElemReader(**self.args)
  1128                 childobj = reader.loads(elem)
  1234                 childobj = reader.loads(elem)
  1129                 obj.add(childobj)
  1235                 obj.add(childobj)
  1150     else:
  1256     else:
  1151         raise exceptions.ParseError("Could not parse tag %s" % tag)
  1257         raise exceptions.ParseError("Could not parse tag %s" % tag)
  1152         
  1258         
  1153 
  1259 
  1154 def get_reader_for_elem(elemname, parent=None):
  1260 def get_reader_for_elem(elemname, parent=None):
  1155     for reader in ConfmlReader.__subclasses__():
  1261     for reader in utils.all_subclasses(ConfmlReader):
  1156         if reader.supported_elem(elemname,parent):
  1262         if reader.supported_elem(elemname,parent):
  1157             return reader()
  1263             return reader()
  1158     raise exceptions.ConePersistenceError("No reader for given elem %s under %s found!" % (elemname, parent))
  1264     raise exceptions.ConePersistenceError("No reader for given elem %s under %s found!" % (elemname, parent))
  1159 
  1265 
  1160 def get_writer_for_class(classname):
  1266 def get_writer_for_class(classname):
  1161     for writer in ConfmlWriter.__subclasses__():
  1267     for writer in utils.all_subclasses(ConfmlWriter):
  1162         if writer.supported_class(classname):
  1268         if writer.supported_class(classname):
  1163             return writer ()
  1269             return writer ()
  1164     raise exceptions.ConePersistenceError("No writer for given class found! %s" % classname)
  1270     raise exceptions.ConePersistenceError("No writer for given class found! %s" % classname)