configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/genconfmlplugin.py
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
--- a/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/genconfmlplugin.py	Fri Mar 12 08:30:17 2010 +0200
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/genconfmlplugin.py	Tue Aug 10 14:29:28 2010 +0300
@@ -26,6 +26,7 @@
 import xslttransformer
 import codecs
 import tempfile
+import pkg_resources
 import tempfile
 
 try:
@@ -39,7 +40,6 @@
         except ImportError:
             from xml.etree import ElementTree
 
-import __init__
 
 from cone.public import exceptions,plugin,utils,api
 from cone.confml import persistentconfml
@@ -52,7 +52,7 @@
     IMPL_TYPE_ID = "gcfml"
     
     
-    def __init__(self,ref,configuration, output='output', linesep=os.linesep, reader=None):
+    def __init__(self,ref,configuration, output='', linesep=os.linesep, reader=None):
         """
         Overloading the default constructor
         """
@@ -63,7 +63,7 @@
         self.xslt_temp_file_name = os.path.join(tempfile.gettempdir(), "genconfml_temp_%i.xslt" % os.getpid())
         self.set_output_root(output)
         self.linesep = linesep
-        self._flatconfig = None
+        self.flatconfig = None
         self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid())
         self.reader = reader
 
@@ -71,19 +71,28 @@
         """
         Generate the given implementation.
         """
+        self.context = context
         self.create_output()
         return 
     
     def get_refs(self):
+        """
+        Get the list of references used inside this gcfml object.
+        """
         result = []
+        refs = []
         for ref in self.reader.settings:
             # Process the reference, so that it will work with has_ref().
             # E.g. 'MyFeature/MySetting' -> 'MyFeature.MySetting'
             #      'MyFeature/*          -> 'MyFeature'
             ref = ref.replace('/', '.')
-            if ref.endswith('.*'):
-                ref = ref[:-2]
-            result.append(ref)
+            refs.append(ref)
+            
+        # Traverse through actual features in the default view, to get a full list 
+        # of refs in case of wildcard usage
+        dview = self.configuration.get_default_view()
+        for fea in dview.get_features(refs):
+            result.append(fea.fqr)
         return result
       
     def list_output_files(self):
@@ -113,7 +122,7 @@
         """ Generate all output """
         resource = self.configuration.get_resource(self.ref)
         write_element_enc(self.reader.stylesheet_elem, self.xslt_temp_file_name, self.reader.stylesheet_output_enc)
-        gen = Generator()
+        gen = Generator(self)
         
         target = self.reader.target
         if target == None: target = ""
@@ -126,10 +135,12 @@
         
         self.logger.info('Generating %s' % output_file)
         
-        flatted_conf_as_element = persistentconfml.ConfmlWriter().dumps(self.flatconfig)
+        flatted_conf_as_element = persistentconfml.ConfmlWriter().dumps(self.get_flatconfig())
         postprocessed_element = self.post_process_flattening(flatted_conf_as_element)
         write_element_enc(postprocessed_element, self.temp_confml_file, self.reader.stylesheet_output_enc)
-        gen.generate(self.configuration, resource, output_file, self.xslt_temp_file_name, self.reader.settings, self.reader.stylesheet_output_enc)
+        gen.generate(self.context, resource, output_file, self.xslt_temp_file_name, self.reader.settings, self.reader.stylesheet_output_enc,
+                     line_ending_style = self.reader.line_ending_style)
+
       
     def post_process_flattening(self, element):
         """
@@ -144,21 +155,20 @@
             new_doc = "<?xml version=\"1.0\"?><configuration>" + ElementTree.tostring(data_element) + "</configuration>"
         return ElementTree.fromstring(new_doc)
 
-    @property
-    def flatconfig(self):
-      """ 
-      Create a flat configuration from the current configuration with the given setting refs.
-      Take the last configuration element, which will contain the data elements
-      """ 
-      if not self._flatconfig:
-          try:
-              cf = confflattener.ConfigurationFlattener()
-              self._flatconfig = api.Configuration()
-              cf.flat(self.configuration, self.reader.settings, self._flatconfig)
-          except (exceptions.ConeException, TypeError, Exception), e:
-              utils.log_exception(self.logger, 'Failed to flat configuration with settings %s. Exception: %s' % (self.reader.settings, e))
-              raise exceptions.ConeException('Failed to flat configuration. Exception: %s' % e)
-      return self._flatconfig
+    def get_flatconfig(self):
+        """ 
+        Create a flat configuration from the current configuration with the given setting refs.
+        Take the last configuration element, which will contain the data elements
+        """ 
+        if not self.flatconfig:
+            try:
+                cf = confflattener.ConfigurationFlattener()
+                self.flatconfig = api.Configuration()
+                cf.flat(self.configuration, self.reader.settings, self.flatconfig)
+            except (exceptions.ConeException, TypeError, Exception), e:
+                utils.log_exception(self.logger, 'Failed to flat configuration with settings %s. Exception: %s' % (self.reader.settings, e))
+                raise exceptions.ConeException('Failed to flat configuration. Exception: %s' % e)
+        return self.flatconfig
 
 
 def write_element(element, output, linesep=os.linesep):
@@ -221,7 +231,7 @@
         try:
             tempfile.write(ElementTree.tostring(element))
         except Exception, e:
-            raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e))
+            raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (tempfile, e))
     else:
         raise exceptions.ConeException('Cannot write element to file, because None element passed or not Element passed.')
     
@@ -230,6 +240,8 @@
     Parses a single gcfml file
     """ 
     NAMESPACE = 'http://www.s60.com/xml/genconfml/1'
+    NAMESPACE_ID = 'gcfml'
+    ROOT_ELEMENT_NAME = 'file'
     IGNORED_NAMESPACES = ['http://www.w3.org/1999/XSL/Transform', 
                           'http://www.w3.org/2001/xinclude']
     FILE_EXTENSIONS = ['gcfml']
@@ -251,17 +263,27 @@
         reader = GenconfmlImplReader()
         reader.from_etree(etree)
         return GenconfmlImpl(resource_ref, configuration, reader=reader)
-            
+    
+    @classmethod
+    def get_schema_data(cls):
+        return pkg_resources.resource_string('genconfmlplugin', 'xsd/gcfml.xsd')
+        
     def from_etree(self, etree):
         self.stylesheet = self.parse_stylesheet(etree)
         self.settings = self.parse_settings(etree)
-        self.name = self.parse_name(etree)
-        self.subdir = self.parse_subdir(etree)        
-        self.target = self.parse_target(etree)
+        self.target = etree.get('target', '')
+        self.name = etree.get('name', '')
+        self.subdir = etree.get('subdir', '')
+        self.line_ending_style = etree.get('lineEndingStyle')
         self.stylesheet_elem = self.parse_stylesheet_elem(etree)
         self.stylesheet_output_enc = self.parse_stylesheet_output_enc(etree)
         self.nss = self.parse_stylesheet_nss(etree)
         
+        if self.line_ending_style not in (None, 'CRLF', 'LF'):
+            raise exceptions.ImplmlParseError(
+                "Invalid line ending style '%s' (should be omitted or one "
+                "of ['CRLF', 'LF'])" % self.line_ending_style)
+        
         return
 
     def parse_target(self, etree):
@@ -271,8 +293,8 @@
         
         target = ""
         for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
-          if elem != None:
-              target = elem.get('target')
+            if elem != None:
+                target = elem.get('target')
         
         return target
     
@@ -283,8 +305,8 @@
         
         name = ""
         for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
-          if elem != None:
-              name = elem.get('name')
+            if elem != None:
+                name = elem.get('name')
         
         return name
 
@@ -295,8 +317,8 @@
         
         subdir = ""
         for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
-          if elem != None:
-              subdir = elem.get('subdir')
+            if elem != None:
+                subdir = elem.get('subdir')
         if subdir == None:
             subdir = ""
         
@@ -350,21 +372,21 @@
         settings = []
         
         for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
-          if elem != None:
-              setting_elems = elem.findall("{%s}setting" % self.namespaces[2])
-              for setting_elem in setting_elems:
-                  if setting_elem != None:
-                      settings.append(setting_elem.get('ref'))
-        
+            if elem != None:
+                setting_elems = elem.findall("{%s}setting" % self.namespaces[2])
+                for setting_elem in setting_elems:
+                    if setting_elem != None:
+                        settings.append(setting_elem.get('ref'))
         return settings
     
 class Generator(object):
     """
     Genconfml generator
     """ 
-    def __init__(self):
+    def __init__(self, implml):
         self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid())
-        pass
+        self.context = None
+        self.implml = implml
 
     def post_process_flattening(self, element):
         """
@@ -380,17 +402,25 @@
         return ElementTree.fromstring(new_doc)
 
 
-    def generate(self, configuration, input, output, xslt, settings, enc=sys.getdefaultencoding()):
+    def generate(self, context, input, output, xslt, settings, enc=sys.getdefaultencoding(),
+                 line_ending_style=None):
         """
         Generates output
         """
+        self.context = context
         self.logger = logging.getLogger('cone.gcfml{%s}' % input.path)
 
+        if line_ending_style == 'LF':
+            linesep = '\n'
+        else:
+            linesep = '\r\n'
         
         try:
             tf = xslttransformer.XsltTransformer()
-            tf.transform_lxml(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), output, enc)
-            #tf.transform_4s(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), output, enc)
+            result = tf.transform_lxml(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), enc, linesep)
+            if not self.filter_file_writing(result):
+                self.write_string_to_file(result, output, enc)
+
         except (exceptions.ConeException, TypeError, Exception), e:
             logging.getLogger('cone.gcfml').warning('Failed to do XSLT tranformation. Exception: %s' % e)
             raise exceptions.ConeException('Failed to do XSLT tranformation. Exception: %s' % e)
@@ -399,3 +429,32 @@
         if not logging.getLogger('cone').getEffectiveLevel() != 10:
             os.remove(os.path.abspath(self.temp_confml_file))
             os.remove(os.path.abspath(xslt))
+
+    def filter_file_writing(self, string):
+        """
+        Returns True if writing result file should be ignored.
+        """
+        string = string.rstrip('\n\r')
+        if string == '' or string == '<?xml version="1.0" encoding="UTF-16"?>' or \
+            string == '<?xml version="1.0" encoding="UTF-8"?>':
+            return True
+        
+        return False
+
+    def write_string_to_file(self, string, output, enc):
+        """
+        Writes string to file
+        """
+        try:
+            
+            #fl = codecs.open(outfile, 'w', enc)
+            fl = self.context.create_file(output, 
+                                          implementation=self.implml,
+                                          mode='w',
+                                          encoding=enc)
+            fl.write(string)
+            fl.close()
+            
+        except Exception, e:
+            logging.getLogger('cone.gcfml').error('Cannot write Element to file (%s). Exception: %s' % (output, e))
+            raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e))