configurationengine/source/cone/confml/persistentconfml.py
changeset 0 2e8eeb919028
child 3 e7e0ae78773e
equal deleted inserted replaced
-1:000000000000 0:2e8eeb919028
       
     1 #
       
     2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 #
       
    16 import re
       
    17 import logging
       
    18 import xml.parsers.expat
       
    19 try:
       
    20     from cElementTree import ElementTree
       
    21 except ImportError:
       
    22     try:    
       
    23         from elementtree import ElementTree
       
    24     except ImportError:
       
    25         try:
       
    26             from xml.etree import cElementTree as ElementTree
       
    27         except ImportError:
       
    28             from xml.etree import ElementTree
       
    29 
       
    30 """ cone specific imports """
       
    31 from cone.public import persistence, exceptions, api, utils, container
       
    32 from cone.confml import model
       
    33 
       
    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"]
       
    36 XLINK_NAMESPACES         = ["http://www.w3.org/1999/xlink"]
       
    37 SCHEMA_NAMESPACES        = ["http://www.w3.org/2001/XMLSchema"]
       
    38 CV_NAMESPACE             = {"http://www.nokia.com/xml/cpf-id/1": "cv"}
       
    39 MODEL                    = model
       
    40 
       
    41 def dumps(obj, indent=True):
       
    42     etree = ConfmlWriter().dumps(obj)
       
    43     if indent:
       
    44         persistence.indent(etree)
       
    45     return ElementTree.tostring(etree)
       
    46 
       
    47 def loads(xml):
       
    48     return ConfmlReader().loads(xml)
       
    49 
       
    50 
       
    51 
       
    52 class ConfmlWriter(persistence.ConeWriter):
       
    53     """
       
    54     """ 
       
    55     def dumps(self, obj):
       
    56         """
       
    57         @param obj: The object 
       
    58         """
       
    59         """ Make sure that the object is mapped to an object in this model """
       
    60         mobj = obj._get_mapper('confml').map_object(obj)
       
    61         writer = get_writer_for_class(mobj.__class__.__name__)
       
    62         return writer.dumps(obj)
       
    63 
       
    64 class ConfmlReader(persistence.ConeReader):
       
    65     """
       
    66     """ 
       
    67     def loads(self, xmlstr):
       
    68         """
       
    69         @param xml: The xml which to read. reads only the first object. 
       
    70         """
       
    71         reader = get_reader_for_elem("configuration")
       
    72         etree = utils.etree.fromstring(xmlstr)
       
    73         return reader.loads(etree)
       
    74 
       
    75 
       
    76 class ConfigurationWriter(ConfmlWriter):
       
    77     """
       
    78     Writes a single Configuration project confml file.
       
    79     """ 
       
    80     @classmethod
       
    81     def supported_class(cls, classname):
       
    82         """
       
    83         Class method to determine if this ConfmlWriter supports writing
       
    84         of the given class name
       
    85         """
       
    86         if classname=="Configuration" or \
       
    87            classname=="ConfmlConfiguration" :
       
    88             return True
       
    89         else:
       
    90             return False
       
    91 
       
    92     def __init__(self):
       
    93         self.configuration_namespace = CONFIGURATION_NAMESPACES[0]
       
    94         self.include_namespace       = INCLUDE_NAMESPACES[0]
       
    95         self.xlink_namespace         = XLINK_NAMESPACES[0]
       
    96         self.schema_namespace        = SCHEMA_NAMESPACES[0]
       
    97     
       
    98     def dumps(self,obj,indent=True):
       
    99         elem = ElementTree.Element("configuration")
       
   100         if self.configuration_namespace:
       
   101             elem.set("xmlns",self.configuration_namespace)
       
   102         if self.include_namespace:
       
   103             elem.set("xmlns:xi",self.include_namespace)
       
   104         if self.include_namespace:
       
   105             elem.set("xmlns:xlink",self.xlink_namespace)
       
   106         if self.schema_namespace:
       
   107             elem.set("xmlns:xs",self.schema_namespace)
       
   108         elem.set("name",obj.get_name()) 
       
   109         for child in obj._objects():
       
   110             """ Make sure that the object is mapped to an object in this model """
       
   111             mobj = child._get_mapper('confml').map_object(child)
       
   112             writer = get_writer_for_class(mobj.__class__.__name__)
       
   113             childelem = writer.dumps(child)
       
   114             elem.append(childelem)
       
   115         return elem
       
   116  
       
   117 
       
   118 class ConfigurationReader(ConfmlReader):
       
   119     """
       
   120     Parses a single CPF configuration project root confml file. Parses the XInclude statements to 
       
   121     find out the layers inside the project
       
   122     """ 
       
   123     @classmethod
       
   124     def supported_elem(cls, elemname, parent=None):
       
   125         """
       
   126         Class method to determine if this ConfmlWriter supports writing
       
   127         of the given elem name
       
   128         """
       
   129         if elemname=="configuration":
       
   130             return True
       
   131         else:
       
   132             return False
       
   133 
       
   134     def __init__(self):
       
   135         self.configuration_namespaces  = CONFIGURATION_NAMESPACES
       
   136         self.include_namespaces        = INCLUDE_NAMESPACES
       
   137         self.schema_namespaces         = SCHEMA_NAMESPACES
       
   138 
       
   139     def loads(self, etree):
       
   140         configuration = model.ConfmlConfiguration("")
       
   141         configuration.set_name(etree.get("name") or 'unknown') 
       
   142         configuration.set_ref(etree.get("name") or 'unknown')
       
   143         for elem in etree.getchildren():
       
   144             # At the moment we ignore the namespace of elements
       
   145             (namespace,elemname) = get_elemname(elem.tag)
       
   146             try:
       
   147                 reader = get_reader_for_elem(elemname)
       
   148                 obj = reader.loads(elem)
       
   149                 if obj:
       
   150                     configuration.add(obj)
       
   151             except exceptions.ConePersistenceError,e:
       
   152                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
       
   153                 continue
       
   154         return configuration
       
   155 
       
   156 
       
   157 class MetaWriter(ConfmlWriter):
       
   158     @classmethod
       
   159     def supported_class(cls, classname):
       
   160         """
       
   161         Class method to determine if this ConfmlWriter supports writing
       
   162         of the given class name
       
   163         """
       
   164         if classname=="ConfmlMeta":
       
   165             return True
       
   166         else:
       
   167             return False
       
   168 
       
   169     def dumps(self, obj):
       
   170         """
       
   171         @param obj: The Configuration object 
       
   172         """
       
   173         
       
   174         elem = ElementTree.Element("meta")
       
   175         for metaproperty in obj:
       
   176             prefix = CV_NAMESPACE.get(metaproperty.ns, "")
       
   177             if prefix != "":
       
   178                 #Including namespace to metadata element as well            
       
   179                 elem.set(("xmlns:%s" % prefix), metaproperty.ns)
       
   180                 childelem = ElementTree.Element(prefix + ":" + metaproperty.tag)
       
   181             else:
       
   182                 childelem = ElementTree.Element(metaproperty.tag)
       
   183             if metaproperty.value != None:
       
   184                 childelem.text = metaproperty.value
       
   185             for attr in metaproperty.attrs:
       
   186                 childelem.set(attr, metaproperty.attrs[attr])
       
   187             elem.append(childelem)
       
   188         return elem
       
   189 
       
   190 
       
   191 class MetaReader(ConfmlReader):
       
   192     @classmethod
       
   193     def supported_elem(cls, elemname, parent=None):
       
   194         """
       
   195         Class method to determine if this ConfmlWriter supports reading
       
   196         of the given elem name
       
   197         """
       
   198         if elemname=="meta":
       
   199             return True
       
   200         else:
       
   201             return False
       
   202 
       
   203     def loads(self,etree):
       
   204         metaelem = model.ConfmlMeta()
       
   205         for elem in etree.getchildren():            
       
   206             (namespace,elemname) = get_elemname(elem.tag)
       
   207             attributes = {}
       
   208             for key in elem.keys():
       
   209                 attributes[key] = elem.get(key)
       
   210             
       
   211             metaprop = model.ConfmlMetaProperty(elemname, elem.text, namespace, attrs=attributes)
       
   212             metaelem.append(metaprop)
       
   213         return metaelem
       
   214 
       
   215 
       
   216 class DescWriter(ConfmlWriter):
       
   217     """
       
   218     """ 
       
   219     @classmethod
       
   220     def supported_class(cls, classname):
       
   221         """
       
   222         Class method to determine if this ConfmlWriter supports writing
       
   223         of the given class name
       
   224         """
       
   225         if classname=="ConfmlDescription":
       
   226             return True
       
   227         else:
       
   228             return False
       
   229 
       
   230     def dumps(self, obj):
       
   231         """
       
   232         @param obj: The Configuration object 
       
   233         """
       
   234         elem = ElementTree.Element('desc')
       
   235         elem.text = obj.text
       
   236         return elem
       
   237 
       
   238 
       
   239 class DescReader(ConfmlReader):
       
   240     @classmethod
       
   241     def supported_elem(cls, elemname, parent=None):
       
   242         """
       
   243         Class method to determine if this ConfmlReader supports reading
       
   244         of the given elem name
       
   245         """
       
   246         if elemname=="desc":
       
   247             return True
       
   248         else:
       
   249             return False
       
   250 
       
   251     def loads(self,elem):
       
   252         desc = model.ConfmlDescription(elem.text)
       
   253         return desc
       
   254 
       
   255 class ConfigurationProxyWriter(ConfmlWriter):
       
   256     """
       
   257     """ 
       
   258     @classmethod
       
   259     def supported_class(cls, classname):
       
   260         """
       
   261         Class method to determine if this ConfmlWriter supports writing
       
   262         of the given class name
       
   263         """
       
   264         if classname=="ConfigurationProxy":
       
   265             return True
       
   266         else:
       
   267             return False
       
   268 
       
   269     def dumps(self, obj):
       
   270         """
       
   271         @param obj: The Configuration object 
       
   272         """
       
   273         elem = self.to_include(obj.path)
       
   274         return elem
       
   275 
       
   276     def to_include(self,include):
       
   277         elem = ElementTree.Element("xi:include",{"href":include})
       
   278         return elem 
       
   279 
       
   280 class ConfigurationProxyReader(ConfmlReader):
       
   281     """
       
   282     """ 
       
   283     @classmethod
       
   284     def supported_elem(cls, elemname, parent=None):
       
   285         """
       
   286         Class method to determine if this ConfmlWriter supports reading
       
   287         of the given elem name
       
   288         """
       
   289         if elemname=="include":
       
   290             return True
       
   291         else:
       
   292             return False
       
   293 
       
   294     def loads(self, elem):
       
   295         """
       
   296         @param elem: The xml include elem
       
   297         """
       
   298         
       
   299         return api.ConfigurationProxy(self.parse_include(elem))
       
   300 
       
   301     def parse_include(self,include):
       
   302         #print "Found include %s" % include.get('href').replace('#/','')
       
   303         return include.get('href').replace('#/','')
       
   304 
       
   305 
       
   306 class FeatureWriter(ConfmlWriter):
       
   307     @classmethod
       
   308     def supported_class(cls, classname):
       
   309         """
       
   310         Class method to determine if this ConfmlWriter supports writing
       
   311         of the given class name
       
   312         """
       
   313         if classname=="ConfmlFeature" or \
       
   314            classname=="Feature":
       
   315             return True
       
   316         else:
       
   317             return False
       
   318 
       
   319     def dumps(self, obj):
       
   320         """
       
   321         @param obj: The Configuration object 
       
   322         """
       
   323         elem = ElementTree.Element('feature', 
       
   324                                    {'ref' : obj.get_ref(),
       
   325                                     'name' : obj.get_name()})
       
   326         if obj.get_type():
       
   327             elem.set('type', obj.get_type())
       
   328         for child in obj._objects():
       
   329             """ Make sure that the object is mapped to an object in this model """
       
   330             mobj = child._get_mapper('confml').map_object(child)
       
   331             writer = get_writer_for_class(mobj.__class__.__name__)
       
   332             childelem = writer.dumps(child)
       
   333             if childelem != None:
       
   334                 elem.append(childelem)
       
   335         return elem
       
   336 
       
   337 
       
   338 class FeatureReader(ConfmlReader):
       
   339     """
       
   340     """ 
       
   341     @classmethod
       
   342     def supported_elem(cls, elemname, parent=None):
       
   343         """
       
   344         Class method to determine if this ConfmlWriter supports reading
       
   345         of the given elem name
       
   346         """
       
   347         if elemname=="feature":
       
   348             return True
       
   349         else:
       
   350             return False
       
   351 
       
   352     def loads(self, elem):
       
   353         """
       
   354         @param elem: The xml include elem
       
   355         """
       
   356         type = elem.get('type')
       
   357         if type == 'sequence':
       
   358             feature = api.FeatureSequence(elem.get('ref'))
       
   359         else:
       
   360             feature = model.ConfmlFeature(elem.get('ref'))
       
   361         if elem.get('name'):
       
   362             feature.set_name(elem.get('name'))
       
   363         feature.set_type(type)
       
   364         for elem in elem.getchildren():
       
   365             # At the moment we ignore the namespace of elements
       
   366             (namespace,elemname) = get_elemname(elem.tag)
       
   367             try:
       
   368                 reader = get_reader_for_elem(elemname)
       
   369                 obj = reader.loads(elem)
       
   370                 feature.add(obj)
       
   371             except exceptions.ConePersistenceError,e:
       
   372                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
       
   373                 continue
       
   374         return feature
       
   375 
       
   376 
       
   377 class OptionWriter(ConfmlWriter):
       
   378     @classmethod
       
   379     def supported_class(cls, classname):
       
   380         """
       
   381         Class method to determine if this ConfmlWriter supports writing
       
   382         of the given class name
       
   383         """
       
   384         if classname=="Option":
       
   385             return True
       
   386         else:
       
   387             return False
       
   388 
       
   389     def dumps(self, obj):
       
   390         """
       
   391         @param obj: The Option object 
       
   392         """
       
   393         
       
   394         objdict = {}
       
   395         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()
       
   397         if obj.map is not None: objdict['map'] = obj.map
       
   398         if obj.relevant is not None: objdict['relevant'] = obj.relevant
       
   399         elem = ElementTree.Element('option', objdict)
       
   400         
       
   401         return elem
       
   402 
       
   403 
       
   404 class OptionReader(ConfmlReader):
       
   405     """
       
   406     """ 
       
   407     @classmethod
       
   408     def supported_elem(cls, elemname, parent=None):
       
   409         """
       
   410         Class method to determine if this ConfmlWriter supports reading
       
   411         of the given elem name
       
   412         """
       
   413         if elemname=="option":
       
   414             return True
       
   415         else:
       
   416             return False
       
   417 
       
   418     def loads(self, elem):
       
   419         """
       
   420         @param elem: The xml include elem
       
   421         """
       
   422         name = elem.get('name')
       
   423         value = elem.get('value')
       
   424         optmap = elem.get('map')
       
   425         if value == None and optmap == None:
       
   426             logging.getLogger('cone').warning("Encountered option with no value")
       
   427             option = None
       
   428         else:
       
   429             option = api.Option(name, value, map=optmap, relevant=elem.get('relevant'))
       
   430         return option
       
   431 
       
   432 
       
   433 class IconWriter(ConfmlWriter):
       
   434     @classmethod
       
   435     def supported_class(cls, classname):
       
   436         """
       
   437         Class method to determine if this ConfmlWriter supports writing
       
   438         of the given class name
       
   439         """
       
   440         if classname=="ConfmlIcon":
       
   441             return True
       
   442         else:
       
   443             return False
       
   444 
       
   445     def dumps(self, obj):
       
   446         """
       
   447         @param obj: The Option object 
       
   448         """
       
   449         elem = ElementTree.Element('icon', 
       
   450                                    {'xlink:href' : obj.href})
       
   451         return elem
       
   452 
       
   453 
       
   454 class IconReader(ConfmlReader):
       
   455     """
       
   456     """ 
       
   457     @classmethod
       
   458     def supported_elem(cls, elemname, parent=None):
       
   459         """
       
   460         Class method to determine if this ConfmlWriter supports reading
       
   461         of the given elem name
       
   462         """
       
   463         if elemname=="icon":
       
   464             return True
       
   465         else:
       
   466             return False
       
   467 
       
   468     def loads(self, elem):
       
   469         """
       
   470         @param elem: The xml include elem
       
   471         """
       
   472         href = elem.get('{%s}href' % XLINK_NAMESPACES[0])
       
   473         obj = model.ConfmlIcon(href)
       
   474         return obj
       
   475 
       
   476 
       
   477 class PropertyWriter(ConfmlWriter):
       
   478     @classmethod
       
   479     def supported_class(cls, classname):
       
   480         """
       
   481         Class method to determine if this ConfmlWriter supports writing
       
   482         of the given class name
       
   483         """
       
   484         if classname=="ConfmlProperty":
       
   485             return True
       
   486         else:
       
   487             return False
       
   488 
       
   489     def dumps(self, obj):
       
   490         """
       
   491         @param obj: The Option object 
       
   492         """
       
   493         elem = ElementTree.Element('property')
       
   494         if obj.name != None:
       
   495             elem.set('name', obj.name)
       
   496         if obj.value != None:
       
   497             elem.set('value', obj.value)
       
   498         if obj.unit != None:
       
   499             elem.set('unit', obj.unit)
       
   500         return elem
       
   501 
       
   502 
       
   503 class PropertyReader(ConfmlReader):
       
   504     """
       
   505     """ 
       
   506     @classmethod
       
   507     def supported_elem(cls, elemname, parent=None):
       
   508         """
       
   509         Class method to determine if this ConfmlWriter supports reading
       
   510         of the given elem name
       
   511         """
       
   512         if elemname=="property":
       
   513             return True
       
   514         else:
       
   515             return False
       
   516 
       
   517     def loads(self, elem):
       
   518         """
       
   519         @param elem: The xml include elem
       
   520         """
       
   521         option = model.ConfmlProperty(name=elem.get('name'),value=elem.get('value'), unit=elem.get('unit'))
       
   522         return option
       
   523 
       
   524 
       
   525 class XmlSchemaFacetWriter(ConfmlWriter):
       
   526     MAPPING = {'ConfmlLength'       : 'xs:length',
       
   527                'ConfmlMinLength'    : 'xs:minLength',
       
   528                'ConfmlMaxLength'    : 'xs:maxLength',
       
   529                'ConfmlMinInclusive' : 'xs:minInclusive',
       
   530                'ConfmlMaxInclusive' : 'xs:maxInclusive',
       
   531                'ConfmlMinExclusive' : 'xs:minExclusive',
       
   532                'ConfmlMaxExclusive' : 'xs:maxExclusive',
       
   533                'ConfmlPattern'      : 'xs:pattern',
       
   534                'ConfmlTotalDigits'  : 'xs:totalDigits'}
       
   535     
       
   536     @classmethod
       
   537     def supported_class(cls, classname):
       
   538         return classname in cls.MAPPING
       
   539     
       
   540     def dumps(self, obj):
       
   541         """
       
   542         @param obj: The facet object 
       
   543         """
       
   544         
       
   545         classname = obj.__class__.__name__
       
   546         elem = ElementTree.Element(self.MAPPING[classname])
       
   547         if obj.value != None:
       
   548             elem.set('value', str(obj.value))
       
   549         return elem
       
   550 
       
   551 class XmlSchemaFacetReader(ConfmlReader):
       
   552     MAPPING = {'length'       : model.ConfmlLength,
       
   553                'minLength'    : model.ConfmlMinLength,
       
   554                'maxLength'    : model.ConfmlMaxLength,
       
   555                'minInclusive' : model.ConfmlMinInclusive,
       
   556                'maxInclusive' : model.ConfmlMaxInclusive,
       
   557                'minExclusive' : model.ConfmlMinExclusive,
       
   558                'maxExclusive' : model.ConfmlMaxExclusive,
       
   559                'pattern'      : model.ConfmlPattern,
       
   560                'totalDigits'  : model.ConfmlTotalDigits}
       
   561     
       
   562     @classmethod
       
   563     def supported_elem(cls, elemname, parent=None):
       
   564         """
       
   565         Class method to determine if this ConfmlWriter supports reading
       
   566         of the given elem name
       
   567         """
       
   568         return elemname in cls.MAPPING
       
   569     
       
   570     def loads(self, elem):
       
   571         """
       
   572         @param elem: The XML schema facet element
       
   573         """
       
   574         elem_name = utils.xml.split_tag_namespace(elem.tag)[1]
       
   575         facet_class = self.MAPPING[elem_name]
       
   576         obj = facet_class(elem.get('value'))
       
   577         return obj
       
   578 
       
   579 
       
   580 class DataWriter(ConfmlWriter):
       
   581     @classmethod
       
   582     def supported_class(cls, classname):
       
   583         """
       
   584         Class method to determine if this ConfmlWriter supports writing
       
   585         of the given class name
       
   586         """
       
   587         if classname=="Data":
       
   588             return True
       
   589         if classname=="DataContainer":
       
   590             return True
       
   591         else:
       
   592             return False
       
   593 
       
   594     def dumps(self, obj):
       
   595         """
       
   596         @param obj: The Data object 
       
   597         """
       
   598         # Create a data hierarchy of the 
       
   599         elem = ElementTree.Element(obj.get_ref())
       
   600         if hasattr(obj,'get_value') and obj.get_value() and not obj.get_map():
       
   601             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:
       
   605             elem.set('template','true')
       
   606         if hasattr(obj,'policy') and obj.policy != '':
       
   607             elem.set('extensionPolicy',obj.policy)
       
   608         for child in obj._objects():
       
   609             writer = DataWriter()
       
   610             childelem = writer.dumps(child)
       
   611             if childelem != None:
       
   612                 elem.append(childelem)
       
   613         return elem
       
   614 
       
   615 
       
   616 class DataReader(ConfmlReader):
       
   617     """
       
   618     """ 
       
   619     @classmethod
       
   620     def supported_elem(cls, elemname, parent=None):
       
   621         """
       
   622         Class method to determine if this ConfmlWriter supports reading
       
   623         of the given elem name
       
   624         """
       
   625         if elemname=="data":
       
   626             return True
       
   627         else:
       
   628             return False
       
   629 
       
   630     def loads(self, elem):
       
   631         """
       
   632         @param elem: The xml include elem
       
   633         """
       
   634         
       
   635         (namespace,elemname) = get_elemname(elem.tag)
       
   636         obj = api.DataContainer(elemname, container=True)
       
   637         for elem in elem.getchildren():
       
   638             try:
       
   639                 reader = ElemReader(attr='data')
       
   640                 childobj = reader.loads(elem)
       
   641                 obj.add(childobj)
       
   642             except exceptions.ConePersistenceError,e:
       
   643                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
       
   644                 continue
       
   645         return obj
       
   646 
       
   647 
       
   648 class ViewWriter(ConfmlWriter):
       
   649     @classmethod
       
   650     def supported_class(cls, classname):
       
   651         """
       
   652         Class method to determine if this ConfmlWriter supports writing
       
   653         of the given class name
       
   654         """
       
   655         if classname=="View" or \
       
   656            classname=="ConfmlView":
       
   657             return True
       
   658         else:
       
   659             return False
       
   660 
       
   661     def dumps(self, obj):
       
   662         """
       
   663         @param obj: The Configuration object 
       
   664         """
       
   665         elem = ElementTree.Element('view', 
       
   666                                    {'id' : obj.get_ref(),
       
   667                                     'name' : obj.get_name()})
       
   668         for child in obj._objects():
       
   669             """ Make sure that the object is mapped to an object in this model """
       
   670             mobj = child._get_mapper('confml').map_object(child)
       
   671             writer = get_writer_for_class(mobj.__class__.__name__)
       
   672             childelem = writer.dumps(child)
       
   673             if childelem != None:
       
   674                 elem.append(childelem)
       
   675         return elem
       
   676 
       
   677 
       
   678 class ViewReader(ConfmlReader):
       
   679     """
       
   680     """ 
       
   681     @classmethod
       
   682     def supported_elem(cls, elemname, parent=None):
       
   683         """
       
   684         Class method to determine if this ConfmlWriter supports reading
       
   685         of the given elem name
       
   686         """
       
   687         if elemname=="view":
       
   688             return True
       
   689         else:
       
   690             return False
       
   691 
       
   692     def loads(self, elem):
       
   693         """
       
   694         @param elem: The xml include elem
       
   695         """
       
   696         vid = elem.get('id')
       
   697         name = elem.get('name')
       
   698         view = model.ConfmlView(name, id=vid)
       
   699         for elem in elem.getchildren():
       
   700             # At the moment we ignore the namespace of elements
       
   701             (namespace,elemname) = get_elemname(elem.tag)
       
   702             try:
       
   703                 reader = get_reader_for_elem(elemname)
       
   704                 obj = reader.loads(elem)
       
   705                 view.add(obj)
       
   706             except exceptions.ConePersistenceError,e:
       
   707                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
       
   708                 continue
       
   709         return view
       
   710 
       
   711 
       
   712 class GroupWriter(ConfmlWriter):
       
   713     @classmethod
       
   714     def supported_class(cls, classname):
       
   715         """
       
   716         Class method to determine if this ConfmlWriter supports writing
       
   717         of the given class name
       
   718         """
       
   719         if classname=="Group" or classname=="ConfmlGroup":
       
   720             return True
       
   721         else:
       
   722             return False
       
   723 
       
   724     def dumps(self, obj):
       
   725         """
       
   726         @param obj: The Configuration object 
       
   727         """
       
   728         elem = ElementTree.Element('group', 
       
   729                                    {'name' : obj.get_name()})
       
   730         for child in obj._objects():
       
   731             """ Make sure that the object is mapped to an object in this model """
       
   732             mobj = child._get_mapper('confml').map_object(child)
       
   733             writer = get_writer_for_class(mobj.__class__.__name__)
       
   734             childelem = writer.dumps(child)
       
   735             if childelem != None:
       
   736                 elem.append(childelem)
       
   737         return elem
       
   738 
       
   739 
       
   740 class GroupReader(ConfmlReader):
       
   741     """
       
   742     """ 
       
   743     @classmethod
       
   744     def supported_elem(cls, elemname, parent=None):
       
   745         """
       
   746         Class method to determine if this ConfmlWriter supports reading
       
   747         of the given elem name
       
   748         """
       
   749         if elemname=='group':
       
   750             return True
       
   751         else:
       
   752             return False
       
   753 
       
   754     def loads(self, elem):
       
   755         """
       
   756         @param elem: The xml include elem
       
   757         """
       
   758         gname = elem.get('name')
       
   759         gref = utils.resourceref.to_dref(gname).replace('.','_')
       
   760         group = model.ConfmlGroup(gref, name=gname)
       
   761         for elem in elem.getchildren():
       
   762             # At the moment we ignore the namespace of elements
       
   763             (namespace,elemname) = get_elemname(elem.tag)
       
   764             try:
       
   765                 reader = get_reader_for_elem(elemname, 'group')
       
   766                 obj = reader.loads(elem)
       
   767                 if obj != None:
       
   768                     group.add(obj)
       
   769             except exceptions.ConePersistenceError,e:
       
   770                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
       
   771                 continue
       
   772         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 
       
   821 
       
   822 class ConfmlSettingWriter(ConfmlWriter):
       
   823     @classmethod
       
   824     def supported_class(cls, classname):
       
   825         """
       
   826         Class method to determine if this ConfmlWriter supports writing
       
   827         of the given class name
       
   828         """
       
   829         if classname=="ConfmlSetting" or \
       
   830            classname=="ConfmlStringSetting" or \
       
   831            classname=="ConfmlIntSetting" or \
       
   832            classname=="ConfmlRealSetting" or \
       
   833            classname=="ConfmlBooleanSetting" or \
       
   834            classname=="ConfmlSelectionSetting" or \
       
   835            classname=="ConfmlMultiSelectionSetting" or \
       
   836            classname=="ConfmlDateSetting" or \
       
   837            classname=="ConfmlTimeSetting" or \
       
   838            classname=="ConfmlDateTimeSetting" or \
       
   839            classname=="ConfmlDurationSetting" or \
       
   840            classname=="ConfmlFileSetting" or \
       
   841            classname=="ConfmlFolderSetting" or \
       
   842            classname=="FeatureSequence" or \
       
   843            classname=="ConfmlSequenceSetting":
       
   844             return True
       
   845         else:
       
   846             return False
       
   847 
       
   848     def dumps(self, obj):
       
   849         """
       
   850         @param obj: The Configuration object 
       
   851         """
       
   852         elem = ElementTree.Element('setting', 
       
   853                                    {'ref' : obj.get_ref(),
       
   854                                     'name' : obj.get_name()})
       
   855         if obj.type:
       
   856             elem.set('type', obj.get_type())
       
   857         if hasattr(obj,'minOccurs'):
       
   858             elem.set('minOccurs', str(obj.minOccurs))
       
   859         if hasattr(obj,'maxOccurs'):
       
   860             elem.set('maxOccurs', str(obj.maxOccurs))
       
   861         if hasattr(obj,'readOnly') and obj.readOnly != None:
       
   862             elem.set('readOnly', str(obj.readOnly).lower())
       
   863         if hasattr(obj,'required') and obj.required != None:
       
   864             elem.set('required', str(obj.required).lower())
       
   865         if hasattr(obj,'constraint') and obj.constraint != None:
       
   866             elem.set('constraint', obj.constraint)
       
   867         if hasattr(obj,'relevant') and obj.relevant != None:
       
   868             elem.set('relevant', obj.relevant)
       
   869         if hasattr(obj,'mapKey') and obj.mapKey is not None:
       
   870             elem.set('mapKey', str(obj.mapKey))
       
   871         if hasattr(obj,'mapValue') and obj.mapValue is not None:
       
   872             elem.set('mapValue', str(obj.mapValue))
       
   873             
       
   874         for child in obj._objects():
       
   875             """ Make sure that the object is mapped to an object in this model """
       
   876             mobj = child._get_mapper('confml').map_object(child)
       
   877             writer = get_writer_for_class(mobj.__class__.__name__)
       
   878             childelem = writer.dumps(child)
       
   879             if childelem != None:
       
   880                 elem.append(childelem)
       
   881         return elem
       
   882 
       
   883 
       
   884 class ConfmlSettingReader(ConfmlReader):
       
   885     """
       
   886     """ 
       
   887     @classmethod
       
   888     def supported_elem(cls, elemname, parent=None):
       
   889         """
       
   890         Class method to determine if this ConfmlWriter supports reading
       
   891         of the given elem name
       
   892         """
       
   893         if parent and not (parent=='feature' or parent=='setting'):
       
   894              return False
       
   895         if elemname=='setting':
       
   896             return True
       
   897         else:
       
   898             return False
       
   899 
       
   900     def loads(self, elem):
       
   901         """
       
   902         @param elem: The xml include elem
       
   903         """
       
   904         typedef = elem.get('type')
       
   905         if typedef == 'sequence':
       
   906             map_key = elem.get('mapKey')
       
   907             map_value = elem.get('mapValue')
       
   908             feature = model.ConfmlSequenceSetting(elem.get('ref'), mapKey=map_key, mapValue=map_value)
       
   909         elif typedef == 'int':
       
   910             feature = model.ConfmlIntSetting(elem.get('ref'))
       
   911         elif typedef == 'boolean':
       
   912             feature = model.ConfmlBooleanSetting(elem.get('ref'))
       
   913         elif typedef == 'selection':
       
   914             feature = model.ConfmlSelectionSetting(elem.get('ref'))
       
   915         elif typedef == 'multiSelection':
       
   916             feature = model.ConfmlMultiSelectionSetting(elem.get('ref'))
       
   917         elif typedef == 'string':
       
   918             feature = model.ConfmlStringSetting(elem.get('ref'))
       
   919         elif typedef == 'real':
       
   920             feature = model.ConfmlRealSetting(elem.get('ref'))
       
   921         elif typedef == 'file':
       
   922             feature = model.ConfmlFileSetting(elem.get('ref'))
       
   923         elif typedef == 'folder':
       
   924             feature = model.ConfmlFolderSetting(elem.get('ref'))
       
   925         elif typedef == 'date':
       
   926             feature = model.ConfmlDateSetting(elem.get('ref'))
       
   927         elif typedef == 'time':
       
   928             feature = model.ConfmlTimeSetting(elem.get('ref'))
       
   929         elif typedef == 'dateTime':
       
   930             feature = model.ConfmlDateTimeSetting(elem.get('ref'))
       
   931         elif typedef == 'duration':
       
   932             feature = model.ConfmlDurationSetting(elem.get('ref'))
       
   933         
       
   934            
       
   935         else:
       
   936             # Handle the default setting as int type
       
   937             feature = model.ConfmlSetting(elem.get('ref'), type=None)
       
   938         
       
   939         if elem.get('name'):
       
   940             feature.set_name(elem.get('name'))
       
   941         if elem.get('minOccurs'):
       
   942             feature.minOccurs = int(elem.get('minOccurs'))
       
   943         if elem.get('maxOccurs'):
       
   944             feature.maxOccurs = int(elem.get('maxOccurs'))
       
   945         if elem.get('readOnly'):
       
   946             feature.readOnly = elem.get('readOnly') == 'true' or False
       
   947         if elem.get('required'):
       
   948             feature.required = elem.get('required') == 'true' or False
       
   949         if elem.get('constraint'):
       
   950             feature.constraint = elem.get('constraint')
       
   951         if elem.get('relevant'):
       
   952             feature.relevant = elem.get('relevant')
       
   953         
       
   954         for elem in elem.getchildren():
       
   955             # At the moment we ignore the namespace of elements
       
   956             (namespace,elemname) = get_elemname(elem.tag)
       
   957             try:
       
   958                 reader = get_reader_for_elem(elemname)
       
   959                 obj = reader.loads(elem)
       
   960                 if obj != None:
       
   961                     feature.add(obj,container.APPEND)
       
   962                 else:
       
   963                     logging.getLogger('cone').warning("Invalid child %s in %s" % (elem,feature.name))
       
   964             except exceptions.ConePersistenceError,e:
       
   965                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
       
   966                 continue
       
   967         return feature
       
   968 
       
   969 
       
   970 class ConfmlLocalPathWriter(ConfmlWriter):
       
   971     @classmethod
       
   972     def supported_class(cls, classname):
       
   973         """
       
   974         Class method to determine if this ConfmlWriter supports writing
       
   975         of the given class name
       
   976         """
       
   977         if classname=="ConfmlLocalPath":
       
   978             return True
       
   979         else:
       
   980             return False
       
   981 
       
   982     def dumps(self, obj):
       
   983         """
       
   984         @param obj: The ConfmlLocalPath object 
       
   985         """
       
   986         elem = ElementTree.Element('localPath')
       
   987         if obj.readOnly:
       
   988             elem.set('readOnly', unicode(obj.readOnly))
       
   989         return elem
       
   990 
       
   991 
       
   992 class ConfmlLocalPathReader(ConfmlReader):
       
   993     """
       
   994     """ 
       
   995     @classmethod
       
   996     def supported_elem(cls, elemname, parent=None):
       
   997         """
       
   998         Class method to determine if this ConfmlWriter supports reading
       
   999         of the given elem name
       
  1000         """
       
  1001         if elemname=="localPath":
       
  1002             return True
       
  1003         else:
       
  1004             return False
       
  1005 
       
  1006     def loads(self, elem):
       
  1007         """
       
  1008         @param elem: The xml include elem
       
  1009         """
       
  1010         return model.ConfmlLocalPath(readOnly=elem.get('readOnly'))
       
  1011 
       
  1012 
       
  1013 class ConfmlTargetPathWriter(ConfmlWriter):
       
  1014     @classmethod
       
  1015     def supported_class(cls, classname):
       
  1016         """
       
  1017         Class method to determine if this ConfmlWriter supports writing
       
  1018         of the given class name
       
  1019         """
       
  1020         if classname=="ConfmlTargetPath":
       
  1021             return True
       
  1022         else:
       
  1023             return False
       
  1024 
       
  1025     def dumps(self, obj):
       
  1026         """
       
  1027         @param obj: The ConfmlLocalPath object 
       
  1028         """
       
  1029         elem = ElementTree.Element('targetPath')
       
  1030         if obj.readOnly:
       
  1031             elem.set('readOnly', unicode(obj.readOnly))
       
  1032         return elem
       
  1033 
       
  1034 
       
  1035 class ConfmlTargetPathReader(ConfmlReader):
       
  1036     """
       
  1037     """ 
       
  1038     @classmethod
       
  1039     def supported_elem(cls, elemname, parent=None):
       
  1040         """
       
  1041         Class method to determine if this ConfmlWriter supports reading
       
  1042         of the given elem name
       
  1043         """
       
  1044         if elemname=="targetPath":
       
  1045             return True
       
  1046         else:
       
  1047             return False
       
  1048 
       
  1049     def loads(self, elem):
       
  1050         """
       
  1051         @param elem: The xml include elem
       
  1052         """
       
  1053         return model.ConfmlTargetPath(readOnly=elem.get('readOnly'))
       
  1054 
       
  1055 
       
  1056 class DummyWriter(ConfmlWriter):
       
  1057     """
       
  1058     Dummy writer is executed on ConE model elements that are not supposed to go to the confml file
       
  1059     """ 
       
  1060     @classmethod
       
  1061     def supported_class(cls, classname):
       
  1062         """
       
  1063         Class method to determine if this ConfmlWriter supports writing
       
  1064         of the given class name
       
  1065         """
       
  1066         if classname=="_FeatureProxy":
       
  1067             return True
       
  1068         else:
       
  1069             return False
       
  1070 
       
  1071     def dumps(self, obj):
       
  1072         return None
       
  1073 
       
  1074 
       
  1075 
       
  1076 class RfsReader(ConfmlReader):
       
  1077     """
       
  1078     """ 
       
  1079     @classmethod
       
  1080     def supported_elem(cls, elemname, parent=None):
       
  1081         """
       
  1082         Class method to determine if this ConfmlWriter supports reading
       
  1083         of the given elem name
       
  1084         """
       
  1085         if elemname=="rfs":
       
  1086             return True
       
  1087         else:
       
  1088             return False
       
  1089 
       
  1090     def loads(self, elem):
       
  1091         """
       
  1092         @param elem: The xml include elem
       
  1093         """
       
  1094         
       
  1095         (namespace,elemname) = get_elemname(elem.tag)
       
  1096         obj = api.DataContainer(elemname, container=True)
       
  1097         for elem in elem.getchildren():
       
  1098             try:
       
  1099                 reader = ElemReader(attr='rfs')
       
  1100                 childobj = reader.loads(elem)
       
  1101                 obj.add(childobj)
       
  1102             except exceptions.ConePersistenceError,e:
       
  1103                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
       
  1104                 continue
       
  1105         return obj
       
  1106 
       
  1107 class ElemReader(ConfmlReader):
       
  1108     def __init__(self, **kwargs):
       
  1109         self.template = kwargs.get('template',False)
       
  1110         self.attr = kwargs.get('attr',None)
       
  1111         self.args = kwargs
       
  1112 
       
  1113     def loads(self, elem):
       
  1114         """
       
  1115         @param elem: The xml include elem
       
  1116         """
       
  1117         (namespace,elemname) = get_elemname(elem.tag)
       
  1118         datavalue = None
       
  1119         if len(list(elem)) == 0:
       
  1120             datavalue = elem.text
       
  1121         datatemplate = elem.get('template') == 'true' or self.template
       
  1122         dataextensionpolicy = elem.get('extensionPolicy') or ''
       
  1123         datamap = elem.get('map')
       
  1124         obj = api.Data(ref=elemname,value=datavalue, template=datatemplate, attr=self.attr,policy=dataextensionpolicy,map=datamap)
       
  1125         for elem in elem.getchildren():
       
  1126             try:
       
  1127                 reader = ElemReader(**self.args)
       
  1128                 childobj = reader.loads(elem)
       
  1129                 obj.add(childobj)
       
  1130             except exceptions.ConePersistenceError,e:
       
  1131                 logging.getLogger('cone').warning("Could not parse element %s. Exception: %s" % (elem,e))
       
  1132                 continue
       
  1133         return obj
       
  1134 
       
  1135 namespace_pattern = re.compile("{(.*)}(.*)")
       
  1136 nonamespace_pattern = re.compile("(.*)")
       
  1137 
       
  1138 def get_elemname(tag):
       
  1139     
       
  1140     ns = namespace_pattern.match(tag)
       
  1141     nn = nonamespace_pattern.match(tag)
       
  1142     if ns:
       
  1143         namespace = ns.group(1)
       
  1144         elemname = ns.group(2)
       
  1145         return (namespace,elemname)
       
  1146     elif nn:
       
  1147         namespace = ""
       
  1148         elemname = nn.group(1)
       
  1149         return (namespace,elemname)
       
  1150     else:
       
  1151         raise exceptions.ParseError("Could not parse tag %s" % tag)
       
  1152         
       
  1153 
       
  1154 def get_reader_for_elem(elemname, parent=None):
       
  1155     for reader in ConfmlReader.__subclasses__():
       
  1156         if reader.supported_elem(elemname,parent):
       
  1157             return reader()
       
  1158     raise exceptions.ConePersistenceError("No reader for given elem %s under %s found!" % (elemname, parent))
       
  1159 
       
  1160 def get_writer_for_class(classname):
       
  1161     for writer in ConfmlWriter.__subclasses__():
       
  1162         if writer.supported_class(classname):
       
  1163             return writer ()
       
  1164     raise exceptions.ConePersistenceError("No writer for given class found! %s" % classname)