50 """ |
50 """ |
51 |
51 |
52 IMPL_TYPE_ID = "gcfml" |
52 IMPL_TYPE_ID = "gcfml" |
53 |
53 |
54 |
54 |
55 def __init__(self,ref,configuration, output='output', linesep=os.linesep, reader=None): |
55 def __init__(self,ref,configuration, output='', linesep=os.linesep, reader=None): |
56 """ |
56 """ |
57 Overloading the default constructor |
57 Overloading the default constructor |
58 """ |
58 """ |
59 plugin.ImplBase.__init__(self,ref,configuration) |
59 plugin.ImplBase.__init__(self,ref,configuration) |
60 self.logger = logging.getLogger('cone.gcfml(%s)' % self.ref) |
60 self.logger = logging.getLogger('cone.gcfml(%s)' % self.ref) |
61 self.errors = False |
61 self.errors = False |
62 self.xstl_etree = None |
62 self.xstl_etree = None |
63 self.xslt_temp_file_name = os.path.join(tempfile.gettempdir(), "genconfml_temp_%i.xslt" % os.getpid()) |
63 self.xslt_temp_file_name = os.path.join(tempfile.gettempdir(), "genconfml_temp_%i.xslt" % os.getpid()) |
64 self.set_output_root(output) |
64 self.set_output_root(output) |
65 self.linesep = linesep |
65 self.linesep = linesep |
66 self._flatconfig = None |
66 self.flatconfig = None |
67 self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid()) |
67 self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid()) |
68 self.reader = reader |
68 self.reader = reader |
69 |
69 |
70 def generate(self, context=None): |
70 def generate(self, context=None): |
71 """ |
71 """ |
72 Generate the given implementation. |
72 Generate the given implementation. |
73 """ |
73 """ |
|
74 self.context = context |
74 self.create_output() |
75 self.create_output() |
75 return |
76 return |
76 |
77 |
77 def get_refs(self): |
78 def get_refs(self): |
|
79 """ |
|
80 Get the list of references used inside this gcfml object. |
|
81 """ |
78 result = [] |
82 result = [] |
|
83 refs = [] |
79 for ref in self.reader.settings: |
84 for ref in self.reader.settings: |
80 # Process the reference, so that it will work with has_ref(). |
85 # Process the reference, so that it will work with has_ref(). |
81 # E.g. 'MyFeature/MySetting' -> 'MyFeature.MySetting' |
86 # E.g. 'MyFeature/MySetting' -> 'MyFeature.MySetting' |
82 # 'MyFeature/* -> 'MyFeature' |
87 # 'MyFeature/* -> 'MyFeature' |
83 ref = ref.replace('/', '.') |
88 ref = ref.replace('/', '.') |
84 if ref.endswith('.*'): |
89 refs.append(ref) |
85 ref = ref[:-2] |
90 |
86 result.append(ref) |
91 # Traverse through actual features in the default view, to get a full list |
|
92 # of refs in case of wildcard usage |
|
93 dview = self.configuration.get_default_view() |
|
94 for fea in dview.get_features(refs): |
|
95 result.append(fea.fqr) |
87 return result |
96 return result |
88 |
97 |
89 def list_output_files(self): |
98 def list_output_files(self): |
90 """ Return a list of output files as an array. """ |
99 """ Return a list of output files as an array. """ |
91 return [self.get_output_filename()] |
100 return [self.get_output_filename()] |
111 |
120 |
112 def create_output(self, layers=None): |
121 def create_output(self, layers=None): |
113 """ Generate all output """ |
122 """ Generate all output """ |
114 resource = self.configuration.get_resource(self.ref) |
123 resource = self.configuration.get_resource(self.ref) |
115 write_element_enc(self.reader.stylesheet_elem, self.xslt_temp_file_name, self.reader.stylesheet_output_enc) |
124 write_element_enc(self.reader.stylesheet_elem, self.xslt_temp_file_name, self.reader.stylesheet_output_enc) |
116 gen = Generator() |
125 gen = Generator(self) |
117 |
126 |
118 target = self.reader.target |
127 target = self.reader.target |
119 if target == None: target = "" |
128 if target == None: target = "" |
120 |
129 |
121 output_file = self.get_output_filename() |
130 output_file = self.get_output_filename() |
124 #if not os.path.exists(os.path.dirname(output_file)): |
133 #if not os.path.exists(os.path.dirname(output_file)): |
125 # os.makedirs(os.path.dirname(output_file)) |
134 # os.makedirs(os.path.dirname(output_file)) |
126 |
135 |
127 self.logger.info('Generating %s' % output_file) |
136 self.logger.info('Generating %s' % output_file) |
128 |
137 |
129 flatted_conf_as_element = persistentconfml.ConfmlWriter().dumps(self.flatconfig) |
138 flatted_conf_as_element = persistentconfml.ConfmlWriter().dumps(self.get_flatconfig()) |
130 postprocessed_element = self.post_process_flattening(flatted_conf_as_element) |
139 postprocessed_element = self.post_process_flattening(flatted_conf_as_element) |
131 write_element_enc(postprocessed_element, self.temp_confml_file, self.reader.stylesheet_output_enc) |
140 write_element_enc(postprocessed_element, self.temp_confml_file, self.reader.stylesheet_output_enc) |
132 gen.generate(self.configuration, resource, output_file, self.xslt_temp_file_name, self.reader.settings, self.reader.stylesheet_output_enc) |
141 gen.generate(self.context, resource, output_file, self.xslt_temp_file_name, self.reader.settings, self.reader.stylesheet_output_enc, |
|
142 line_ending_style = self.reader.line_ending_style) |
|
143 |
133 |
144 |
134 def post_process_flattening(self, element): |
145 def post_process_flattening(self, element): |
135 """ |
146 """ |
136 Pick just data element and build document out of it |
147 Pick just data element and build document out of it |
137 """ |
148 """ |
142 new_doc = "<?xml version=\"1.0\"?><configuration>" + "</configuration>" |
153 new_doc = "<?xml version=\"1.0\"?><configuration>" + "</configuration>" |
143 else: |
154 else: |
144 new_doc = "<?xml version=\"1.0\"?><configuration>" + ElementTree.tostring(data_element) + "</configuration>" |
155 new_doc = "<?xml version=\"1.0\"?><configuration>" + ElementTree.tostring(data_element) + "</configuration>" |
145 return ElementTree.fromstring(new_doc) |
156 return ElementTree.fromstring(new_doc) |
146 |
157 |
147 @property |
158 def get_flatconfig(self): |
148 def flatconfig(self): |
159 """ |
149 """ |
160 Create a flat configuration from the current configuration with the given setting refs. |
150 Create a flat configuration from the current configuration with the given setting refs. |
161 Take the last configuration element, which will contain the data elements |
151 Take the last configuration element, which will contain the data elements |
162 """ |
152 """ |
163 if not self.flatconfig: |
153 if not self._flatconfig: |
164 try: |
154 try: |
165 cf = confflattener.ConfigurationFlattener() |
155 cf = confflattener.ConfigurationFlattener() |
166 self.flatconfig = api.Configuration() |
156 self._flatconfig = api.Configuration() |
167 cf.flat(self.configuration, self.reader.settings, self.flatconfig) |
157 cf.flat(self.configuration, self.reader.settings, self._flatconfig) |
168 except (exceptions.ConeException, TypeError, Exception), e: |
158 except (exceptions.ConeException, TypeError, Exception), e: |
169 utils.log_exception(self.logger, 'Failed to flat configuration with settings %s. Exception: %s' % (self.reader.settings, e)) |
159 utils.log_exception(self.logger, 'Failed to flat configuration with settings %s. Exception: %s' % (self.reader.settings, e)) |
170 raise exceptions.ConeException('Failed to flat configuration. Exception: %s' % e) |
160 raise exceptions.ConeException('Failed to flat configuration. Exception: %s' % e) |
171 return self.flatconfig |
161 return self._flatconfig |
|
162 |
172 |
163 |
173 |
164 def write_element(element, output, linesep=os.linesep): |
174 def write_element(element, output, linesep=os.linesep): |
165 """ |
175 """ |
166 """ |
176 """ |
219 if element != None and ElementTree.iselement(element): |
229 if element != None and ElementTree.iselement(element): |
220 |
230 |
221 try: |
231 try: |
222 tempfile.write(ElementTree.tostring(element)) |
232 tempfile.write(ElementTree.tostring(element)) |
223 except Exception, e: |
233 except Exception, e: |
224 raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e)) |
234 raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (tempfile, e)) |
225 else: |
235 else: |
226 raise exceptions.ConeException('Cannot write element to file, because None element passed or not Element passed.') |
236 raise exceptions.ConeException('Cannot write element to file, because None element passed or not Element passed.') |
227 |
237 |
228 class GenconfmlImplReader(plugin.ReaderBase): |
238 class GenconfmlImplReader(plugin.ReaderBase): |
229 """ |
239 """ |
230 Parses a single gcfml file |
240 Parses a single gcfml file |
231 """ |
241 """ |
232 NAMESPACE = 'http://www.s60.com/xml/genconfml/1' |
242 NAMESPACE = 'http://www.s60.com/xml/genconfml/1' |
|
243 NAMESPACE_ID = 'gcfml' |
|
244 ROOT_ELEMENT_NAME = 'file' |
233 IGNORED_NAMESPACES = ['http://www.w3.org/1999/XSL/Transform', |
245 IGNORED_NAMESPACES = ['http://www.w3.org/1999/XSL/Transform', |
234 'http://www.w3.org/2001/xinclude'] |
246 'http://www.w3.org/2001/xinclude'] |
235 FILE_EXTENSIONS = ['gcfml'] |
247 FILE_EXTENSIONS = ['gcfml'] |
236 |
248 |
237 def __init__(self): |
249 def __init__(self): |
249 def read_impl(cls, resource_ref, configuration, etree): |
261 def read_impl(cls, resource_ref, configuration, etree): |
250 |
262 |
251 reader = GenconfmlImplReader() |
263 reader = GenconfmlImplReader() |
252 reader.from_etree(etree) |
264 reader.from_etree(etree) |
253 return GenconfmlImpl(resource_ref, configuration, reader=reader) |
265 return GenconfmlImpl(resource_ref, configuration, reader=reader) |
254 |
266 |
|
267 @classmethod |
|
268 def get_schema_data(cls): |
|
269 return pkg_resources.resource_string('genconfmlplugin', 'xsd/gcfml.xsd') |
|
270 |
255 def from_etree(self, etree): |
271 def from_etree(self, etree): |
256 self.stylesheet = self.parse_stylesheet(etree) |
272 self.stylesheet = self.parse_stylesheet(etree) |
257 self.settings = self.parse_settings(etree) |
273 self.settings = self.parse_settings(etree) |
258 self.name = self.parse_name(etree) |
274 self.target = etree.get('target', '') |
259 self.subdir = self.parse_subdir(etree) |
275 self.name = etree.get('name', '') |
260 self.target = self.parse_target(etree) |
276 self.subdir = etree.get('subdir', '') |
|
277 self.line_ending_style = etree.get('lineEndingStyle') |
261 self.stylesheet_elem = self.parse_stylesheet_elem(etree) |
278 self.stylesheet_elem = self.parse_stylesheet_elem(etree) |
262 self.stylesheet_output_enc = self.parse_stylesheet_output_enc(etree) |
279 self.stylesheet_output_enc = self.parse_stylesheet_output_enc(etree) |
263 self.nss = self.parse_stylesheet_nss(etree) |
280 self.nss = self.parse_stylesheet_nss(etree) |
264 |
281 |
|
282 if self.line_ending_style not in (None, 'CRLF', 'LF'): |
|
283 raise exceptions.ImplmlParseError( |
|
284 "Invalid line ending style '%s' (should be omitted or one " |
|
285 "of ['CRLF', 'LF'])" % self.line_ending_style) |
|
286 |
265 return |
287 return |
266 |
288 |
267 def parse_target(self, etree): |
289 def parse_target(self, etree): |
268 """ |
290 """ |
269 Parses target from etree |
291 Parses target from etree |
270 """ |
292 """ |
271 |
293 |
272 target = "" |
294 target = "" |
273 for elem in etree.getiterator("{%s}file" % self.namespaces[2]): |
295 for elem in etree.getiterator("{%s}file" % self.namespaces[2]): |
274 if elem != None: |
296 if elem != None: |
275 target = elem.get('target') |
297 target = elem.get('target') |
276 |
298 |
277 return target |
299 return target |
278 |
300 |
279 def parse_name(self, etree): |
301 def parse_name(self, etree): |
280 """ |
302 """ |
281 Parses name from etree |
303 Parses name from etree |
282 """ |
304 """ |
283 |
305 |
284 name = "" |
306 name = "" |
285 for elem in etree.getiterator("{%s}file" % self.namespaces[2]): |
307 for elem in etree.getiterator("{%s}file" % self.namespaces[2]): |
286 if elem != None: |
308 if elem != None: |
287 name = elem.get('name') |
309 name = elem.get('name') |
288 |
310 |
289 return name |
311 return name |
290 |
312 |
291 def parse_subdir(self, etree): |
313 def parse_subdir(self, etree): |
292 """ |
314 """ |
293 Parses subdir from etree |
315 Parses subdir from etree |
294 """ |
316 """ |
295 |
317 |
296 subdir = "" |
318 subdir = "" |
297 for elem in etree.getiterator("{%s}file" % self.namespaces[2]): |
319 for elem in etree.getiterator("{%s}file" % self.namespaces[2]): |
298 if elem != None: |
320 if elem != None: |
299 subdir = elem.get('subdir') |
321 subdir = elem.get('subdir') |
300 if subdir == None: |
322 if subdir == None: |
301 subdir = "" |
323 subdir = "" |
302 |
324 |
303 return subdir |
325 return subdir |
304 |
326 |
348 """ |
370 """ |
349 |
371 |
350 settings = [] |
372 settings = [] |
351 |
373 |
352 for elem in etree.getiterator("{%s}file" % self.namespaces[2]): |
374 for elem in etree.getiterator("{%s}file" % self.namespaces[2]): |
353 if elem != None: |
375 if elem != None: |
354 setting_elems = elem.findall("{%s}setting" % self.namespaces[2]) |
376 setting_elems = elem.findall("{%s}setting" % self.namespaces[2]) |
355 for setting_elem in setting_elems: |
377 for setting_elem in setting_elems: |
356 if setting_elem != None: |
378 if setting_elem != None: |
357 settings.append(setting_elem.get('ref')) |
379 settings.append(setting_elem.get('ref')) |
358 |
|
359 return settings |
380 return settings |
360 |
381 |
361 class Generator(object): |
382 class Generator(object): |
362 """ |
383 """ |
363 Genconfml generator |
384 Genconfml generator |
364 """ |
385 """ |
365 def __init__(self): |
386 def __init__(self, implml): |
366 self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid()) |
387 self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid()) |
367 pass |
388 self.context = None |
|
389 self.implml = implml |
368 |
390 |
369 def post_process_flattening(self, element): |
391 def post_process_flattening(self, element): |
370 """ |
392 """ |
371 Pick just data element and build document out of it |
393 Pick just data element and build document out of it |
372 """ |
394 """ |
378 else: |
400 else: |
379 new_doc = "<?xml version=\"1.0\"?><configuration>" + ElementTree.tostring(data_element) + "</configuration>" |
401 new_doc = "<?xml version=\"1.0\"?><configuration>" + ElementTree.tostring(data_element) + "</configuration>" |
380 return ElementTree.fromstring(new_doc) |
402 return ElementTree.fromstring(new_doc) |
381 |
403 |
382 |
404 |
383 def generate(self, configuration, input, output, xslt, settings, enc=sys.getdefaultencoding()): |
405 def generate(self, context, input, output, xslt, settings, enc=sys.getdefaultencoding(), |
|
406 line_ending_style=None): |
384 """ |
407 """ |
385 Generates output |
408 Generates output |
386 """ |
409 """ |
|
410 self.context = context |
387 self.logger = logging.getLogger('cone.gcfml{%s}' % input.path) |
411 self.logger = logging.getLogger('cone.gcfml{%s}' % input.path) |
388 |
412 |
|
413 if line_ending_style == 'LF': |
|
414 linesep = '\n' |
|
415 else: |
|
416 linesep = '\r\n' |
389 |
417 |
390 try: |
418 try: |
391 tf = xslttransformer.XsltTransformer() |
419 tf = xslttransformer.XsltTransformer() |
392 tf.transform_lxml(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), output, enc) |
420 result = tf.transform_lxml(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), enc, linesep) |
393 #tf.transform_4s(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), output, enc) |
421 if not self.filter_file_writing(result): |
|
422 self.write_string_to_file(result, output, enc) |
|
423 |
394 except (exceptions.ConeException, TypeError, Exception), e: |
424 except (exceptions.ConeException, TypeError, Exception), e: |
395 logging.getLogger('cone.gcfml').warning('Failed to do XSLT tranformation. Exception: %s' % e) |
425 logging.getLogger('cone.gcfml').warning('Failed to do XSLT tranformation. Exception: %s' % e) |
396 raise exceptions.ConeException('Failed to do XSLT tranformation. Exception: %s' % e) |
426 raise exceptions.ConeException('Failed to do XSLT tranformation. Exception: %s' % e) |
397 |
427 |
398 """ Removes template files """ |
428 """ Removes template files """ |
399 if not logging.getLogger('cone').getEffectiveLevel() != 10: |
429 if not logging.getLogger('cone').getEffectiveLevel() != 10: |
400 os.remove(os.path.abspath(self.temp_confml_file)) |
430 os.remove(os.path.abspath(self.temp_confml_file)) |
401 os.remove(os.path.abspath(xslt)) |
431 os.remove(os.path.abspath(xslt)) |
|
432 |
|
433 def filter_file_writing(self, string): |
|
434 """ |
|
435 Returns True if writing result file should be ignored. |
|
436 """ |
|
437 string = string.rstrip('\n\r') |
|
438 if string == '' or string == '<?xml version="1.0" encoding="UTF-16"?>' or \ |
|
439 string == '<?xml version="1.0" encoding="UTF-8"?>': |
|
440 return True |
|
441 |
|
442 return False |
|
443 |
|
444 def write_string_to_file(self, string, output, enc): |
|
445 """ |
|
446 Writes string to file |
|
447 """ |
|
448 try: |
|
449 |
|
450 #fl = codecs.open(outfile, 'w', enc) |
|
451 fl = self.context.create_file(output, |
|
452 implementation=self.implml, |
|
453 mode='w', |
|
454 encoding=enc) |
|
455 fl.write(string) |
|
456 fl.close() |
|
457 |
|
458 except Exception, e: |
|
459 logging.getLogger('cone.gcfml').error('Cannot write Element to file (%s). Exception: %s' % (output, e)) |
|
460 raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e)) |