coverage.py revision 3aa0db4be952157c2842b91a1606cc0edac9e63d
1326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard#!/usr/bin/env python3
2326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
3fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# INTEL CONFIDENTIAL
4fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# Copyright  2013 Intel
5fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# Corporation All Rights Reserved.
6fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard#
7fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# The source code contained or described herein and all documents related to
8fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# the source code ("Material") are owned by Intel Corporation or its suppliers
9fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# or licensors. Title to the Material remains with Intel Corporation or its
10fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# suppliers and licensors. The Material contains trade secrets and proprietary
11fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# and confidential information of Intel or its suppliers and licensors. The
12fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# Material is protected by worldwide copyright and trade secret laws and
13fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# treaty provisions. No part of the Material may be used, copied, reproduced,
14fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# modified, published, uploaded, posted, transmitted, distributed, or
15fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# disclosed in any way without Intels prior express written permission.
16fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard#
17fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# No license under any patent, copyright, trade secret or other intellectual
18fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# property right is granted to or conferred upon you by disclosure or delivery
19fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# of the Materials, either expressly, by implication, inducement, estoppel or
20fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# otherwise. Any license under such intellectual property rights must be
21fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# express and approved by Intel in writing.
22fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard
23326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard"""
24326e39e42a801bff4b61655ebc0e3ff759c208ffKevin RocardGenerate a coverage report by parsing parameter framework log.
25326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
26326e39e42a801bff4b61655ebc0e3ff759c208ffKevin RocardThe coverage report contains the:
27326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard - domain
28326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard - configuration
29326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard - rule
30326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard - criterion
31326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardbasic coverage statistics.
32326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard"""
33326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
34326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardimport xml.dom.minidom
35326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardimport sys
36326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardimport re
37326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardimport logging
38326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
39326e39e42a801bff4b61655ebc0e3ff759c208ffKevin RocardFORMAT = '%(levelname)s: %(message)s'
40326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardlogging.basicConfig(stream=sys.stderr, level=logging.WARNING, format=FORMAT)
41326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardlogger = logging.getLogger("Coverage")
42326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
433aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocardclass CustomError(Exception):
44804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	pass
453aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard
463aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocardclass ChildError(CustomError):
47804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, parent, child):
48804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.parent = parent
49804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.child = child
503aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard
513aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocardclass ChildNotFoundError(ChildError):
52804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __str__(self):
53804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return ("Unable to find the child %s in %s" %
543aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard				(self.child, self.parent))
553aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard
56804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass DuplicatedChildError(ChildError):
57804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __str__(self):
58326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return ("Add existing child %s in %s. Did you restart de PFW ?" %
59326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				(self.child, self.parent))
60804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
61804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass Element():
62326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	"""Root class for all coverage elements"""
63804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "element"
64326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
65804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, name):
66804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
67326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.parent = None
68804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.children = []
69326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
70804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.nbUse = 0
71326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
72804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.name = name
73326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
74326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.debug("New element")
75804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
76804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
77326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def __str__(self):
78804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return  "%s (%s)" % (self.name, self.tag)
79804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
80326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def __eq__(self, compared):
81804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug(lambda : "Comparing:\n%s" % self.dump())
82804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug(lambda : "With:\n%s" % compared.dump())
83326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		result = self.name == compared.name and self.children == compared.children
84804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug("Result is %s" % result)
85804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return result
86326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
87804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
88804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def getName(self, default=""):
89326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return self.name or default
90804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
91804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def hasChildren(self):
92804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return bool(self.children)
93804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
94804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def getChildren(self):
95326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return self.children
96804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
97326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def _getDescendants(self):
98804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for child in self.children:
99326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			yield child
100804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			for descendant in child._getDescendants() :
101804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				yield descendant
102326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
103804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def getChildFromName(self, childName):
104326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
105804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for child in self.children :
106326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
107804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			if child.getName() == childName :
108804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				return child
109326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
110804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug("Child %s not found" % childName, logging.ERROR)
111326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
112326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.debug("Child list :")
113804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
114804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for child in self.children :
115804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.debug("  - %s" % child)
116804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
117326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		raise ChildNotFoundError(self, childName)
118804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
119804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
120804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def addChild(self, child):
121326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.debug("new child: " + child.name)
122804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.children.append(child)
123804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		child._adoptedBy(self)
124326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
125804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _adoptedBy(self, parent):
126804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		assert(not self.parent)
127326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.parent = parent
128804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
129804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _getElementNames(self, elementList):
130326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return (substate.name for substate in elementList)
131804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
132804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _description(self, withCoverage, withNbUse):
133326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		description = self.name
134804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
135326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		if withNbUse or withCoverage :
136326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			description += " has been used " + str(self.nbUse) + " time"
137804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
138804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if withCoverage :
139326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			description += self._coverageFormating(self._getCoverage())
140804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
141804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return description
142804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
143326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
144804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _getCoverage(self):
145326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
146804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		coverageDependance = list(self._getCoverageDependance())
147804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
148804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		nbcoverageDependence = len(coverageDependance)
149804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
150804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if nbcoverageDependence == 0:
151326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			# Coverage makes no sense without any dependence
152804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			return None
153804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
154326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		nbcoverageDependanceUsed = len([element
155804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				for element in coverageDependance
156326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				if element.hasBeenUsed()])
157804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
158804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return nbcoverageDependanceUsed / nbcoverageDependence
159326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
160804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _getCoverageDependance(self):
161804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return self.children
162804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
163804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _coverageFormating(self, coverage):
164326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		# If no coverage provided
165804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if not coverage :
166804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			return ""
167326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
168804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Calculate coverage
169804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return " (%s coverage)" % self._number2percent(coverage)
170804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
171326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	@staticmethod
172804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _number2percent(number):
173804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		"""Format a number to a integer % string
174804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
175326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		example: _number2percent(0.6666) -> "67%"
176326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		"""
177804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return "{0:.0f}%".format(100 * number)
178326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
179804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
180804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _dumpDescription(self, withCoverage, withNbUse):
181326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
182804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug("yelding description")
183804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		yield RankedLine(self._description(withCoverage, withNbUse), lineSuffix="")
184326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
185804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for dumped in self._dumpPropagate(withCoverage, withNbUse) :
186326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			yield dumped
187804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
188804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _dumpPropagate(self, withCoverage, withNbUse):
189804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
190326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		for child in self.children :
191326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			for dumpedDescription in child._dumpDescription(withCoverage, withNbUse) :
192804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				yield dumpedDescription.increasedRank()
193326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
194804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
195804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def dump(self, withCoverage=False, withNbUse=True):
196804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
197326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return "\n".join(
198804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				str(dumpedDescription) for dumpedDescription in
199804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						self._dumpDescription(withCoverage, withNbUse))
200804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
20102726ec37a9686572f825520a04700061ffe5d06Kevin Rocard	def exportToXML(self):
202804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		domElement = xml.dom.minidom.Element(self.tag)
203326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self._XMLaddAttributes(domElement)
204804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
205804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for child in self.children :
206326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			domElement.appendChild(child.exportToXML())
207804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
208326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return domElement
209804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
210804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _XMLaddAttributes(self, domElement):
211326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		attributes = self._getXMLAttributes()
212804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
213804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		coverage = self._getCoverage()
214804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if coverage != None :
215326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			attributes["Coverage"] = self._number2percent(coverage)
216804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
217804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for key, value in attributes.items():
218326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			domElement.setAttribute(key, value)
219804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
220804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _getXMLAttributes(self):
221804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return {
222804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				"Name": self.name,
223804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				"NbUse": str(self.nbUse)
224326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				}
225804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
226804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _incNbUse(self):
227326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.nbUse += 1
228804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
229804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def childUsed(self, child):
230804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self._incNbUse()
231804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Propagate to parent
232326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self._tellParentThatChildUsed()
233804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
234804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _tellParentThatChildUsed(self):
235804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if self.parent :
236326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			self.parent.childUsed(self)
237326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
238804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
239804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def parentUsed(self):
240804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self._incNbUse()
241804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Propagate to children
242804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for child in self.children :
243326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			child.parentUsed()
244804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
245804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def hasBeenUsed(self):
246326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return self.nbUse > 0
247804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
248326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def operationOnChild(self, path, operation):
249804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Stop if path is not consume yet but there is no child
250804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		assert(self.children or not path)
251804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
252804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if path:
253804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			return self._operationPropagate(path, operation)
254326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		else :
255804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.debug("operating on self")
256326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			return operation(self)
257804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
258804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _operationPropagate(self, path, operation):
259326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
260804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		childName = path.pop(0)
261326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		child = self.getChildFromName(childName)
262326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
263326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return child.operationOnChild(path, operation)
264804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
265804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
266326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
267804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def debug(self, stringOrFunction, level=logging.DEBUG):
268804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		"""Print a debug line on stderr in tree form
269804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
270804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		If the debug line is expensive to generate, provide callable
271804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		object, it will be called if log is enable for this level.
272326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		This callable object should return the logline string.
273804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		"""
274804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if logger.isEnabledFor(level):
275804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
276804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			# TODO: use buildin callable if python >= 3.2
277804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			if hasattr(stringOrFunction, "__call__"):
278326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				string = stringOrFunction()
279804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			else:
280804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				string = stringOrFunction
281326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
282804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			rankedLine = DebugRankedLine("%s: %s" % (self, string))
283326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			self._logDebug(rankedLine, level)
284804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
285804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _logDebug(self, rankedLine, level):
286804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
287804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if self.parent:
288326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			self.parent._logDebug(rankedLine.increasedRank(), level)
289326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		else :
290326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			logger.log(level, str(rankedLine))
291326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
292326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
293804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
294804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
295804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass FromDomElement(Element):
296326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def __init__(self, DomElement):
297326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self._initFromDom(DomElement)
298804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		super().__init__(self.name)
299804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
300326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
301326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def _initFromDom(self, DomElement):
302326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.name = DomElement.getAttribute("Name")
303326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
304804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
305804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
306804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass DomElementLocation():
307804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, classConstructor, path=None):
308804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.classConstructor = classConstructor
309804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if path :
310326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			self.path = path
311804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		else :
312326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			self.path = []
313326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
314326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.path.append(classConstructor.tag)
315804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
316326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
317804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass DomPopulatedElement(Element):
318804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	"""Default child populate
319804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
320804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	Look for each dom element with tag specified in self.tag
321326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	and instantiate it with the dom element
322804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	"""
323326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	childClasses = []
324804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
325326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def populate(self, dom):
326804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
327804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for childDomElementLocation in self.childClasses :
328326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
329804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.debug("Looking for child %s in path %s" % (
330326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				childDomElementLocation.path[-1], childDomElementLocation.path))
331804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
332804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			for childDomElement in self._findChildFromTagPath(dom, childDomElementLocation.path) :
333326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
334804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				childElement = childDomElementLocation.classConstructor(childDomElement)
335326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				self.addChild(childElement)
336804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
337804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				childElement.populate(childDomElement)
338804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
339804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _findChildFromTagPath(self, dom, path):
340804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if not path :
341804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			yield dom
342326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		else :
343804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			# Copy list
344326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			path = list(path)
345804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
346804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			tag = path.pop(0)
347804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
348326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			# Find element with tag
349804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.debug("Going to find elements with tag %s in %s" % (tag, dom))
350326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			self.debug(lambda: "Nb of solutions: %s" % len(dom.getElementsByTagName(tag)))
351804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
352326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			for elementByTag in dom.getElementsByTagName(tag) :
353804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
354804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				self.debug("Found element: %s" % elementByTag)
355326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
356804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				# If the same tag is found
357804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				if elementByTag in dom.childNodes :
358804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
359326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard					# Yield next level
360326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard					for element in self._findChildFromTagPath(elementByTag, path) :
361326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard						yield element
362326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
363804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
364804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass Rule(Element):
365804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
366326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def usedIfApplicable(self, criteria):
367804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		childApplicability = (child.usedIfApplicable(criteria)
368326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				for child in self.children)
369804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
370804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		isApplicable = self._isApplicable(criteria, childApplicability)
371326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
372804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if isApplicable :
373804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self._incNbUse()
374326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
375804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug("Rule applicability: %s" % isApplicable)
376326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		assert(isApplicable == True or isApplicable == False)
377326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
378804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return isApplicable
379804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
380cf031996ede8428065b6d7648e34720a1874f5faKevin Rocard
381804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _isApplicable(self, criteria, childApplicability):
382804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Forcing evaluation of all child by the list creation
383804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return all(list(childApplicability))
384326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
385326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
386326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass CriterionRule(FromDomElement, DomPopulatedElement, Rule):
387804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "SelectionCriterionRule"
388804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	childClasses = []
389804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	isApplicableOperations = {
390804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				"Includes" : lambda criterion, value:     criterion.stateIncludes(value),
391804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				"Excludes" : lambda criterion, value: not criterion.stateIncludes(value),
392804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				"Is"       : lambda criterion, value:     criterion.stateIs(value),
393804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				"IsNot"    : lambda criterion, value: not criterion.stateIs(value)
394804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			}
395326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
396804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _initFromDom(self, DomElement):
397804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.selectionCriterion = DomElement.getAttribute("SelectionCriterion")
398804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.matchesWhen = DomElement.getAttribute("MatchesWhen")
399804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.value = DomElement.getAttribute("Value")
400804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.name = "%s %s %s" % (self.selectionCriterion, self.matchesWhen, self.value)
401326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
402804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		applicableOperationWithoutValue = self.isApplicableOperations[self.matchesWhen]
403804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.isApplicableOperation = lambda criterion: applicableOperationWithoutValue(criterion, self.value)
404326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
405804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _isApplicable(self, criteria, childApplicability):
406326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
407804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return criteria.operationOnChild([self.selectionCriterion],
408804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				self.isApplicableOperation)
409326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
410326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
411326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass CompoundRule(FromDomElement, DomPopulatedElement, Rule):
412804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	"""CompoundRule can be of type ALL or ANY"""
413804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "CompoundRule"
414804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	# Declare childClasses but define it at first class instantiation
415804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	childClasses = None
416326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
417804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, dom):
418804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Define childClasses at first class instantiation
419804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if self.childClasses == None :
420804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.childClasses = [DomElementLocation(CriterionRule),
421804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					DomElementLocation(CompoundRule)]
422804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		super().__init__(dom)
423326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
424804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _initFromDom(self, DomElement):
425326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
426804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		type = DomElement.getAttribute("Type")
427804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.ofTypeAll = {"All" : True, "Any" : False}[type]
428804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.name = type
429326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
430804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _isApplicable(self, criteria, childApplicability):
431804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if self.ofTypeAll :
432804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			applicability = super()._isApplicable(criteria, childApplicability)
433804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		else:
434804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			# Forcing evaluation of all child by the list creation
435804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			applicability = any(list(childApplicability))
436326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
437804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return applicability
438326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
439326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass RootRule(DomPopulatedElement, Rule):
440804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "RootRule"
441804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	childClasses = [DomElementLocation(CompoundRule)]
442326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
443804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def populate(self, dom):
444804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		super().populate(dom)
445804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug("Children: %s" % self.children)
446804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# A configuration can only have one or no rule
447804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		assert(len(self.children) <= 1)
448326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
449804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _getCoverageDependance(self):
450804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return self._getDescendants()
451326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
452326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
453326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass CriteronStates(Element):
454804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	"""Root of configuration application criterion state"""
455804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "CriterionStates"
456326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
457804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def parentUsed(self, criteria):
458804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		"""Add criteria to child if not exist, if exist increase it's nbUse"""
459804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self._incNbUse()
460326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
461804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		matches = [child for child in self.children if child == criteria]
462326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
463804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		assert(len(matches) <= 1)
464326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
465804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if matches :
466804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.debug("Criteria state has already been encounter")
467804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			currentcriteria = matches[0]
468804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		else :
469804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.debug("Criteria state has never been encounter, saving it")
470804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			currentcriteria = criteria
471804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.addChild(criteria)
472326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
473804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		currentcriteria.parentUsed()
474326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
475326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass IneligibleConfigurationAppliedError(CustomError):
476326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
477326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def __init__(self, configuration, criteria):
478804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.configuration = configuration
479804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.criteria = criteria
480326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
481804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __str__(self):
48297dbd35c75ee252a674aff3d66293d55fc0b35a5Kevin Rocard
483804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return ("Applying ineligible %s, "
484804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			"rule:\n%s\n"
485804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			"Criteria current state:\n%s" %
48697dbd35c75ee252a674aff3d66293d55fc0b35a5Kevin Rocard			(self.configuration, self.configuration.rootRule.dump(), self.criteria.dump()))
487804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
48897dbd35c75ee252a674aff3d66293d55fc0b35a5Kevin Rocard
489804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass Configuration(FromDomElement, DomPopulatedElement):
490804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "Configuration"
491804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	childClasses = []
492804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
493804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, DomElement):
494804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		super().__init__(DomElement)
495804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
49697dbd35c75ee252a674aff3d66293d55fc0b35a5Kevin Rocard		self.rootRule = RootRule("RootRule")
497804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.addChild(self.rootRule)
498804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
499326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.criteronStates = CriteronStates("CriterionStates")
500804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.addChild(self.criteronStates)
501804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
502326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def populate(self, dom):
503804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Delegate to rootRule
504804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.rootRule.populate(dom)
505326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
506804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _getCoverage(self):
507804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Delegate to rootRule
508804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return self.rootRule._getCoverage()
509326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
510804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def used(self, criteria):
511804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
512804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self._incNbUse()
513326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
514804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Propagate use to parents
515326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self._tellParentThatChildUsed()
516804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
517326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		# Propagate to criterion coverage
518804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.criteronStates.parentUsed(criteria.export())
519804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
520326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		# Propagate to rules
521804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if not self.rootRule.usedIfApplicable(criteria) :
522804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
523326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			self.debug("Applied but rule does not match current "
524804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard                       "criteria (parent: %s) " % self.parent.name,
525804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					logging.FATAL)
526326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
527804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			raise IneligibleConfigurationAppliedError(self, criteria.export())
5283aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard
529804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _dumpPropagate(self, withCoverage, withNbUse):
530326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.debug("Going to ask %s for description" % self.rootRule)
531804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for dumpedDescription in self.rootRule._dumpDescription(
532326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				withCoverage=withCoverage,
533804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				withNbUse=withNbUse) :
534804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			yield dumpedDescription.increasedRank()
535804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
536804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug("Going to ask %s for description" % self.criteronStates)
537804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for dumpedDescription in self.criteronStates._dumpDescription(
538804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				withCoverage=False,
539326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				withNbUse=withNbUse) :
540804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			yield dumpedDescription.increasedRank()
541804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
542804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
543804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass Domain(FromDomElement, DomPopulatedElement):
544804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "ConfigurableDomain"
545326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	childClasses = [DomElementLocation(Configuration, ["Configurations"])]
546326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
547326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
548804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass Domains(DomPopulatedElement):
549804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "Domains"
550326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	childClasses = [DomElementLocation(Domain, ["ConfigurableDomains"])]
551326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
552326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
553804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass RankedLine():
554804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, string,
555326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				stringPrefix="|-- ",
556326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				rankString="|   ",
557326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				linePrefix="",
558804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				lineSuffix="\n"):
559804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.string = string
560804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.rank = 0
561804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.stringPrefix = stringPrefix
562804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.rankString = rankString
563804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.linePrefix = linePrefix
564804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.lineSuffix = lineSuffix
565804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
566804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def increasedRank(self):
567804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.rank += 1
568804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return self
569804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
570804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __str__(self):
571804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return self.linePrefix + \
572804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.rank * self.rankString + \
573804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.stringPrefix + \
574804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.string + \
575804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.lineSuffix
576804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
577804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass DebugRankedLine(RankedLine):
578804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
579804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, string, lineSuffix=""):
580326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		super().__init__(string,
581326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				stringPrefix="",
582326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				rankString="   ",
583804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				linePrefix="",
584804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				lineSuffix=lineSuffix)
585804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
586804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
587804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass CriterionState(Element):
588804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "CriterionState"
589326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def used(self):
590326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self._incNbUse()
591326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
592804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
593804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass Criterion(Element):
594804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "Criterion"
595326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	inclusivenessTranslate = {True: "Inclusive", False: "Exclusive"}
596326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
597326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def __init__(self, name, isInclusif, stateNamesList, currentStateNamesList):
598804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		super().__init__(name)
599804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.isInclusif = isInclusif
6003aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard
601804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for state in stateNamesList :
602804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.addChild(CriterionState(state))
603804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
604804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.currentState = []
605556538e2bda03b54bdd82c5813a5286e90a39f67Kevin Rocard
606804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Set current state as provided
607804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.currentState = [self.getChildFromName(childName)
608804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard							for childName in currentStateNamesList]
609556538e2bda03b54bdd82c5813a5286e90a39f67Kevin Rocard
610804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def childUsed(self, child):
611804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.currentState = child
612804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		super().childUsed(child)
613804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
614804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def changeState(self, subStateNames):
615326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.debug("Changing state from: %s to: %s" % (
616804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					list(self._getElementNames(self.currentState)),
617804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					subStateNames))
618326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
619804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		assert(len(subStateNames) > 0 or self.isInclusif)
620804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
621804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		newCurrentState = []
622326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		for subStateName in subStateNames :
623804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			subState = self.getChildFromName(subStateName)
624804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			subState.used()
625804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			newCurrentState.append(subState)
626326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
627804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.currentState = newCurrentState
628804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
629804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self._incNbUse()
630804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self._tellParentThatChildUsed()
631326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
632804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def export(self):
633804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		subStateNames = self._getElementNames(self.currentState)
634804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return Criterion(self.name, self.isInclusif, subStateNames, subStateNames)
635326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
636804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def stateIncludes(self, subStateName):
637804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		subStateCurrentNames = list(self._getElementNames(self.currentState))
638804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
639804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug("Testing if %s is included in %s" % (subStateName, subStateCurrentNames))
640804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
641326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		isIncluded = subStateName in subStateCurrentNames
642804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.debug("IsIncluded: %s" % isIncluded)
643326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
644804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return isIncluded
645804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
646326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
647804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def stateIs(self, subStateNames):
648804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if len(self.currentState) != 1 :
649556538e2bda03b54bdd82c5813a5286e90a39f67Kevin Rocard			return False
650804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		else :
651804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			return self.stateIncludes(subStateNames)
652804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
653556538e2bda03b54bdd82c5813a5286e90a39f67Kevin Rocard	def _getXMLAttributes(self):
654804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		attributes = super()._getXMLAttributes()
655804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		attributes["Type"] = self.inclusivenessTranslate[self.isInclusif]
656804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return attributes
657804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
658326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
659804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass Criteria(Element):
660804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	tag = "Criteria"
661326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
662804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def export(self):
663326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.debug("Exporting criteria")
664804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		assert(self.children)
665804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
666326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		exported = Criteria(self.name)
667804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for child in self.children :
668326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			exported.addChild(child.export())
669326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return exported
670804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
671804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def addChild(self, child):
672804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if child in self.children:
673804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			raise DuplicatedChildError(self, child)
674804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		super().addChild(child)
675326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
676804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass ConfigAppliedWithoutCriteriaError(CustomError):
677804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, configurationName, domainName):
678804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.configurationName = configurationName
679804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.domainName = domainName
6803aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard	def __str__(self):
681326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		return ('Applying configuration "%s" from domain "%s" before declaring criteria' %
682326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				(self.configurationName, self.domainName))
683804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
684326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass ParsePFWlog():
685804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	MATCH = "match"
686804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	ACTION = "action"
687d077c557e360615a67d97ee249260a1ef7919f09Kevin Rocard
688804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, domains, criteria):
689804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
690804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.domains = domains;
691326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.criteria = criteria;
692804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
693804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		configApplicationRegext = r""".*Applying configuration "(.*)" from domain "([^"]*)"""
694804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		matchConfigApplicationLine = re.compile(configApplicationRegext).match
695804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
696326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		criterionCreationRegext = ", ".join([
697804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					r""".*Criterion name: (.*)""",
698804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					r"""type kind: (.*)""",
699804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					r"""current state: (.*)""",
700804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					r"""states: {(.*)}"""
7013aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard				])
7023aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard		matchCriterionCreationLine = re.compile(criterionCreationRegext).match
703804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
704804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		changingCriterionRegext = r""".*Selection criterion changed event: Criterion name: (.*), current state: ([^\n\r]*)"""
705804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		matchChangingCriterionLine = re.compile(changingCriterionRegext).match
706804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
707804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.lineLogTypes = [
708804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					{
709326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard						self.MATCH: matchConfigApplicationLine,
710326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard						self.ACTION: self._configApplication
711804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					}, {
712804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						self.MATCH: matchCriterionCreationLine,
713804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						self.ACTION: self._criterionCreation
714804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					}, {
715804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						self.MATCH: matchChangingCriterionLine,
716804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						self.ACTION: self._changingCriterion
717804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					}
718804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				]
719326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
720804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	@staticmethod
721804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _formatCriterionList(liststring, separator):
722804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		list = liststring.split(separator)
723804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if len(list) == 1 and list[0] == "<none>":
724804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			list = []
725804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return list
726804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
727804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _criterionCreation(self, matchCriterionCreation):
728804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Unpack
729804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		criterionName, criterionType, currentCriterionStates, criterionStates = matchCriterionCreation.group(1, 2, 3, 4)
730326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
731804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		criterionStateList = self._formatCriterionList(criterionStates, ", ")
732804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
733326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		criterionIsInclusif = {"exclusive" : False, "inclusive" : True}[criterionType]
734804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
735804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		currentcriterionStateList = self._formatCriterionList(currentCriterionStates, "|")
736804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
737804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		logger.info("Creating criterion: " + criterionName +
738804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					" (" + criterionType + ") " +
739804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					" with current state: " + str(currentcriterionStateList) +
740804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					", possible states:" + str(criterionStateList))
741804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
742804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.criteria.addChild(Criterion(
743804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					criterionName,
744804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					criterionIsInclusif,
745804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					criterionStateList,
746326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard					currentcriterionStateList
747804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				))
748804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
749804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _changingCriterion(self, matchChangingCriterion):
750804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Unpack
751804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		criterionName, newCriterionSubStateNames = matchChangingCriterion.group(1, 2)
752804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
753804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		newCriterionState = self._formatCriterionList(newCriterionSubStateNames, "|")
754804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
755804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		logger.info("Changing criterion %s to %s" % (criterionName , newCriterionState))
756804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
757326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		path = [criterionName]
758804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		changeCriterionOperation = lambda criterion : criterion.changeState(newCriterionState)
759326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.criteria.operationOnChild(path, changeCriterionOperation)
760804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
761326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	def _configApplication(self, matchConfig):
762804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Unpack
763326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		configurationName, domainName = matchConfig.group(1, 2)
764804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
765804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Check that at least one criterion exist
766804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		if not self.criteria.hasChildren() :
767804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			logger.error("Applying configuration before declaring criteria")
768326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			logger.info("Is the log starting at PFW boot ?")
769804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			raise ConfigAppliedWithoutCriteriaError(configurationName, domainName)
770804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
771804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Change criterion state
772804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		path = [domainName, configurationName]
773804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		usedOperation = lambda element : element.used(self.criteria)
774804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
775804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		logger.info("Applying configuration %s from domain %s" % (
776804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				configurationName, domainName))
777804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
778804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.domains.operationOnChild(path, usedOperation)
779804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
780804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
781804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def _digest(self, lineLogType, lineLog):
782804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		match = lineLogType[self.MATCH](lineLog)
783ea87422e14735633cb8e28de114a18e22eaa82fbKevin Rocard		if match :
784ea87422e14735633cb8e28de114a18e22eaa82fbKevin Rocard			lineLogType[self.ACTION](match)
785326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			return True
786804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return False
787804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
788804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def parsePFWlog(self, lines):
789326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		for lineLog in lines:
790804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
791326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			logger.debug("Parsing line :%s" % lineLog.rstrip())
792804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
7933aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard			digested = (self._digest(lineLogType, lineLog)
794804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					for lineLogType in self.lineLogTypes)
795804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
796804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			if not any(digested):
797326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				logger.debug("Line does not match, dropped")
798804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
799804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
800804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass Root(Element):
8013aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard	tag = "Root"
802804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self, name, dom):
803804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		super().__init__(name)
804804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Create domain tree
805804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.domains = Domains("Domains")
806804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.domains.populate(dom)
807326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		self.addChild(self.domains)
808804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		# Create criterion list
809804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.criteria = Criteria("CriterionRoot")
810804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		self.addChild(self.criteria)
811326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
812804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def exportToXML(self):
813804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		"""Export tree to an xml document"""
814804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		impl = xml.dom.minidom.getDOMImplementation()
815804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		newdoc = impl.createDocument(None, self.name, None)
816326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard		XMLDocElement = newdoc.documentElement
817326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
818804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		for child in self.children:
8199050c81c8f9a63aa95e7230705e00585bd0ecec5Kevin Rocard			XMLDocElement.appendChild(child.exportToXML())
820804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
821804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		return newdoc
822804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
823804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard# ============================
824804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard# Command line argument parser
825326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard# ============================
8269050c81c8f9a63aa95e7230705e00585bd0ecec5Kevin Rocard
827804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
828804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardclass ArgumentParser:
829326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	"""class that parse command line arguments with argparse library
830804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
831326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard	Result of parsing are the class attributes.
832804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	"""
833804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	levelTranslate = [logging.WARNING, logging.INFO, logging.DEBUG]
834326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard
835804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	def __init__(self):
836804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
8379050c81c8f9a63aa95e7230705e00585bd0ecec5Kevin Rocard		try:
838804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			# As argparse is only in the stdlib since python 3.2,
839804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			# testing its availability
840804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			import argparse
841804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
842804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		except ImportError:
8439050c81c8f9a63aa95e7230705e00585bd0ecec5Kevin Rocard			logger.warning("Unable to import argparse "
844804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						   "(parser for command-line options and arguments), "
845804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						   "using default argument values:")
846804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
847804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			logger.warning(" - InputFile: stdin")
848804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.inputFile = sys.stdin
849804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
850804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			logger.warning(" - OutputFile: stdout")
851804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.outputFile = sys.stdout
852804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
853804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			try:
854326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				self.domainsFile = sys.argv[1]
855326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			except IndexError as ex:
856326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard				logger.fatal("No domain file provided (first argument)")
857804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				raise ex
858804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			else:
859804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard				logger.warning(" - Domain file: " + self.domainsFile)
860804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
861804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			logger.warning(" - Output format: xml")
862804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.XMLreport = True
863804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
864804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			logger.warning(" - Debug level: error")
865804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.debugLevel = logging.INFO
866804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		else :
867804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
868804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			myArgParser = argparse.ArgumentParser(description='Generate PFW report')
869804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
870804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			myArgParser.add_argument(
871804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						'domainsFile',
872804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						type=argparse.FileType('r'),
873804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						help="the PFW domain XML file"
874804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					)
875326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			myArgParser.add_argument(
876326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard						'pfwlog', nargs='?',
877326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard						type=argparse.FileType('r'), default=sys.stdin,
878326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard						help="the PFW log file, default stdin"
879326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard					)
880326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard			myArgParser.add_argument(
881326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard						'-o', '--output',
882804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						dest="outputFile",
883804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						type=argparse.FileType('w'), default=sys.stdout,
884804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						help="the coverage report output file, default stdout"
885804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					)
886804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			myArgParser.add_argument(
887804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						'-v', '--verbose',
888804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						dest="debugLevel", default=0,
889804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						action='count',
890804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						help="print debug warnings from warning (default) to debug (-vv)"
891804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					)
892804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
893804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			outputFormatGroupe = myArgParser.add_mutually_exclusive_group(required=False)
894804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
895804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			outputFormatGroupe.add_argument(
896804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						'--xml',
897804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						dest="xmlFlag",
898804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						action='store_true',
899804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						help=" XML coverage output report"
900804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					)
901804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			outputFormatGroupe.add_argument(
902804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						'--raw',
903804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						dest="rawFlag",
904804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						action='store_true',
905804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard						help="raw coverage output report"
906804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard					)
907804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
908804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			# Process command line arguments
909804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			options = myArgParser.parse_args()
910804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
911804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			# Mapping to attributes
912804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.inputFile = options.pfwlog
913804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.outputFile = options.outputFile
914804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.domainsFile = options.domainsFile
915804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
916804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			# Output report in xml if flag not set
917804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.XMLreport = not options.rawFlag
918804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
919804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			# Setting logger level
920804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			levelCapped = min(options.debugLevel, len(self.levelTranslate) - 1)
921804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			self.debugLevel = self.levelTranslate[levelCapped]
922804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
923804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
924804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
925804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocarddef main():
926804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
927804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	errorDuringLogParsing = -1
928804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	errorDuringArgumentParsing = 1
929804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
930804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	try:
931804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		commandLineArguments = ArgumentParser()
932804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	except LookupError as ex:
933804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		logger.error("Error during argument parsing")
934804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		logger.debug(str(ex))
935804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		sys.exit(errorDuringArgumentParsing)
936804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
937804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	# Setting logger level
938804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	logger.setLevel(commandLineArguments.debugLevel)
939804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	logger.info("Log level set to: %s" %
940804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			logging.getLevelName(commandLineArguments.debugLevel))
941804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
942804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	# Create tree from XML
943804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	dom = xml.dom.minidom.parse(commandLineArguments.domainsFile)
944804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
945804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	# Create element tree
946804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	root = Root("Coverage", dom)
947804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
948804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	# Parse PFW events
949804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	parser = ParsePFWlog(root.domains, root.criteria)
950804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
951804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	try:
952804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		parser.parsePFWlog(commandLineArguments.inputFile.readlines())
953804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	except CustomError as ex:
954804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		logger.fatal("Error during parsing log file %s: %s" %
955804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard			(commandLineArguments.inputFile, ex))
956804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		sys.exit(errorDuringLogParsing)
957804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
958804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	# Output report
959804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	outputFile = commandLineArguments.outputFile
960804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
961804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	if not commandLineArguments.XMLreport :
962804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		outputFile.write("%s\n" % root.dump(withCoverage=True, withNbUse=True))
963804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	else :
964804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard		outputFile.write(root.exportToXML().toprettyxml())
965804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
966804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
967804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard# Execute main function if the python interpreter is running this module as the main program
968804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocardif __name__ == "__main__" :
969804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard	main()
970804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard
971804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard