17d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner#!/usr/bin/python2
27d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# -*-coding:utf-8 -*
37d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
47d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# Copyright (c) 2011-2014, Intel Corporation
57d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# All rights reserved.
67d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner#
77d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# Redistribution and use in source and binary forms, with or without modification,
87d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# are permitted provided that the following conditions are met:
97d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner#
107d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# 1. Redistributions of source code must retain the above copyright notice, this
117d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# list of conditions and the following disclaimer.
127d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner#
137d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# 2. Redistributions in binary form must reproduce the above copyright notice,
147d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# this list of conditions and the following disclaimer in the documentation and/or
157d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# other materials provided with the distribution.
167d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner#
177d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# 3. Neither the name of the copyright holder nor the names of its contributors
187d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# may be used to endorse or promote products derived from this software without
197d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# specific prior written permission.
207d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner#
217d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
227d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
237d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
247d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
257d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
267d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
277d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
287d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
297d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
307d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
317d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
327d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
337d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
347d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerimport re
357d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerimport sys
367d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerimport copy
377d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerfrom itertools import izip
387d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerfrom itertools import imap
397d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
407d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# =====================================================================
417d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner""" Context classes, used during propagation and the "to PFW script" step """
427d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# =====================================================================
437d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
447d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass PropagationContextItem(list) :
457d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """Handle an item during the propagation step"""
467d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __copy__(self):
477d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """C.__copy__() -> a shallow copy of C"""
487d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self.__class__(self)
497d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
507d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass PropagationContextElement(PropagationContextItem) :
517d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """Handle an Element during the propagation step"""
527d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getElementsFromName(self, name):
537d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        matchingElements = []
547d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for element in self :
557d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            if element.getName() == name :
567d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                matchingElements.append(element)
577d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return matchingElements
587d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
597d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
607d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass PropagationContextOption(PropagationContextItem) :
617d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """Handle an Option during the propagation step"""
627d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getOptionItems (self, itemName):
637d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        items = []
647d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for options in self :
657d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            items.append(options.getOption(itemName))
667d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return items
677d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
687d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
697d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass PropagationContext() :
707d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """Handle the context during the propagation step"""
717d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__(self, propagationContext=None) :
727d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
737d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if propagationContext == None :
747d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self._context = {
757d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                "DomainOptions" : PropagationContextOption() ,
767d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                "Configurations" : PropagationContextElement() ,
777d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                "ConfigurationOptions" : PropagationContextOption() ,
787d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                "Rules" : PropagationContextElement() ,
797d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                "PathOptions" : PropagationContextOption() ,
807d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        }
817d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        else :
827d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self._context = propagationContext
837d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
847d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def copy(self):
857d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return a copy of the context"""
867d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        contextCopy = self._context.copy()
877d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
887d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for key in iter(self._context) :
897d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            contextCopy[key] = contextCopy[key].__copy__()
907d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
917d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self.__class__(contextCopy)
927d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
937d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getDomainOptions (self):
947d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self._context["DomainOptions"]
957d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
967d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getConfigurations (self):
977d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self._context["Configurations"]
987d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
997d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getConfigurationOptions (self):
1007d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self._context["ConfigurationOptions"]
1017d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1027d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getRules (self):
1037d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self._context["Rules"]
1047d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1057d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getPathOptions (self):
1067d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self._context["PathOptions"]
1077d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1087d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1097d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# =====================================================
1107d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner"""Element option container"""
1117d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# =====================================================
1127d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1137d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Options () :
1147d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """handle element options"""
1157d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__(self, options=[], optionNames=[]) :
1167d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.options = dict(izip(optionNames, options))
1177d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # print(options,optionNames,self.options)
1187d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1197d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1207d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __str__(self) :
1217d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        ops2str = []
1227d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for name, argument in self.options.items() :
1237d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            ops2str.append(str(name) + "=\"" + str(argument) + "\"")
1247d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1257d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return " ".join(ops2str)
1267d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1277d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getOption(self, name):
1287d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """get option by its name, if it does not exist return empty string"""
1297d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self.options.get(name, "")
1307d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1317d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def setOption(self, name, newOption):
1327d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """set option by its name"""
1337d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.options[name] = newOption
1347d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1357d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def copy (self):
1367d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """D.copy() -> a shallow copy of D"""
1377d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        copy = Options()
1387d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        copy.options = self.options.copy()
1397d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return copy
1407d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1417d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ====================================================
1427d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner"""Definition of all element class"""
1437d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ====================================================
1447d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1457d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Element(object):
1467d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """ implement a basic element
1477d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1487d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    It is the class base for all other elements as Domain, Configuration..."""
1497d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "unknown"
1507d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionNames = ["Name"]
1517d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    childWhiteList = []
1527d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionDelimiter = " "
1537d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1547d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__(self, line=None) :
1557d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1567d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if line == None :
1577d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self.option = Options([], self.optionNames)
1587d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        else :
1597d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self.option = self.optionFromLine(line)
1607d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1617d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.children = []
1627d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1637d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def optionFromLine(self, line) :
1647d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # get ride of spaces
1657d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        line = line.strip()
1667d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1677d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        options = self.extractOptions(line)
1687d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1697d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return Options(options, self.optionNames)
1707d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1717d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def extractOptions(self, line) :
1727d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return the line splited by the optionDelimiter atribute
1737d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1747d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Option list length is less or equal to the optionNames list length
1757d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """
1767d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        options = line.split(self.optionDelimiter, len(self.optionNames) - 1)
1777d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1787d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # get ride of leftover spaces
1797d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        optionsStrip = list(imap(str.strip, options))
1807d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1817d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return optionsStrip
1827d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1837d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def addChild(self, child, append=True) :
1847d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """ A.addChid(B) -> add B to A child list if B class name is in A white List"""
1857d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        try:
1867d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            # Will raise an exception if this child is not in the white list
1877d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self.childWhiteList.index(child.__class__.__name__)
1887d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            # If no exception was raised, add child to child list
1897d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1907d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            if append :
1917d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                self.children.append(child)
1927d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            else :
1937d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                self.children.insert(0, child)
1947d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1957d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        except ValueError:
1967d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            # the child class is not in the white list
1977d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            raise ChildNotPermitedError("", self, child)
1987d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
1997d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def addChildren(self, children, append=True) :
2007d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """Add a list of child"""
2017d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if append:
2027d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            # Add children at the end of the child list
2037d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self.children.extend(children)
2047d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        else:
2057d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            # Add children at the begining of the child list
2067d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self.children = children + self.children
2077d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2087d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def childrenToString(self, prefix=""):
2097d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return raw printed children """
2107d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        body = ""
2117d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for child in self.children :
2127d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            body = body + child.__str__(prefix)
2137d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2147d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return body
2157d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2167d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __str__(self, prefix="") :
2177d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return raw printed element"""
2187d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        selfToString = prefix + " " + self.tag + " " + str(self.option)
2197d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return selfToString + "\n" + self.childrenToString(prefix + "\t")
2207d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2217d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def extractChildrenByClass(self, classTypeList) :
2227d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return all children whose class is in the list argument
2237d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2247d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return a list of all children whose class in the list "classTypeList" (second arguments)"""
2257d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        selectedChildren = []
2267d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2277d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for child in  self.children :
2287d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            for classtype in classTypeList :
2297d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                if child.__class__ == classtype :
2307d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    selectedChildren.append(child)
2317d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    break
2327d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return selectedChildren
2337d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2347d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def propagate (self, context=PropagationContext()):
2357d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """call the propagate method of all children"""
2367d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for child in  self.children :
2377d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            child.propagate(context)
2387d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2397d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getName(self):
2407d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return name option value. If none return "" """
2417d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self.option.getOption("Name")
2427d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2437d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def setName(self, name):
2447d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.option.setOption("Name", name)
2457d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2467d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def translate(self, translator):
2477d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for child in self.children:
2487d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            child.translate(translator)
2497d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2507d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ----------------------------------------------------------
2517d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2527d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass ElementWithTag (Element):
2537d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """Element of this class are declared with a tag  => line == "tag: .*" """
2547d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def extractOptions(self, line) :
2557d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        lineWithoutTag = line.split(":", 1)[-1].strip()
2567d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        options = super(ElementWithTag, self).extractOptions(lineWithoutTag)
2577d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return options
2587d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2597d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ----------------------------------------------------------
2607d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2617d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass ElementWithInheritance(Element):
2627d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def propagate (self, context=PropagationContext) :
2637d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """propagate some proprieties to children"""
2647d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2657d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # copy the context so that everything that hapend next will only affect
2667d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # children
2677d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        contextCopy = context.copy()
2687d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2697d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # check for inheritance
2707d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.Inheritance(contextCopy)
2717d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2727d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # call the propagate method of all children
2737d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        super(ElementWithInheritance, self).propagate(contextCopy)
2747d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2757d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2767d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass ElementWithRuleInheritance(ElementWithInheritance):
2777d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """class that will give to its children its rules"""
2787d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def ruleInheritance(self, context):
2797d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """Add its rules to the context and get context rules"""
2807d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2817d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # extract all children rule and operator
2827d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        childRules = self.extractChildrenByClass([Operator, Rule])
2837d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2847d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # get context rules
2857d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        contextRules = context.getRules()
2867d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2877d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # adopt rules of the beginning of the context
2887d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.addChildren(contextRules, append=False)
2897d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2907d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # add previously extract rules to the context
2917d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        contextRules += childRules
2927d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2937d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2947d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ----------------------------------------------------------
2957d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2967d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass EmptyLine (Element) :
2977d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """This class represents an empty line.
2987d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
2997d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    Will raise "EmptyLineWarning" exception at instanciation."""
3007d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3017d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "emptyLine"
3027d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(r"[ \t]*\n?$").match
3037d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__ (self, line):
3047d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner       raise EmptyLineWarning(line)
3057d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3067d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ----------------------------------------------------------
3077d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3087d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Commentary(Element):
3097d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """This class represents a commentary.
3107d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3117d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    Will raise "CommentWarning" exception at instanciation."""
3127d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3137d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "commentary"
3147d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionNames = ["comment"]
3157d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(r"#").match
3167d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__ (self, line):
3177d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner       raise CommentWarning(line)
3187d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3197d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ----------------------------------------------------------
3207d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3217d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Path (ElementWithInheritance) :
3227d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """class implementing the "path = value" concept"""
3237d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "path"
3247d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionNames = ["Name", "value"]
3257d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(r".+=").match
3267d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionDelimiter = "="
3277d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3287d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def translate(self, translator):
3297d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        translator.setParameter(self.getName(), self.option.getOption("value"))
3307d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3317d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def Inheritance (self, context) :
3327d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """check for path name inheritance"""
3337d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.OptionsInheritance(context)
3347d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3357d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def OptionsInheritance (self, context) :
3367d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """make configuration name inheritance """
3377d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3387d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        context.getPathOptions().append(self.option.copy())
3397d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.setName("/".join(context.getPathOptions().getOptionItems("Name")))
3407d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3417d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3427d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass GroupPath (Path, ElementWithTag) :
3437d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "component"
3447d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(tag + r" *:").match
3457d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionNames = ["Name"]
3467d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    childWhiteList = ["Path", "GroupPath"]
3477d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3487d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getPathNames (self) :
3497d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """Return the list of all path child name"""
3507d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3517d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        pathNames = []
3527d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3537d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        paths = self.extractChildrenByClass([Path])
3547d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for path in paths :
3557d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            pathNames.append(path.getName())
3567d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3577d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        groupPaths = self.extractChildrenByClass([GroupPath])
3587d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for groupPath in groupPaths :
3597d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            pathNames += groupPath.getPathNames()
3607d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3617d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return pathNames
3627d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3637d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def translate(self, translator):
3647d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for child in self.extractChildrenByClass([Path, GroupPath]):
3657d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            child.translate(translator)
3667d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3677d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ----------------------------------------------------------
3687d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3697d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Rule (Element) :
3707d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """class implementing the rule concept
3717d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3727d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    A rule is composed of a criterion, a rule type and an criterion state.
3737d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    It should not have any child and is propagated to all configuration in parent descendants.
3747d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """
3757d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3767d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "rule"
3777d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionNames = ["criterion", "type", "element"]
3787d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(r"[a-zA-Z0-9_.]+ +(Is|IsNot|Includes|Excludes) +[a-zA-Z0-9_.]+").match
3797d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    childWhiteList = []
3807d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3817d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def PFWSyntax (self, prefix=""):
3827d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3837d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        script = prefix + \
3847d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    self.option.getOption("criterion") + " " + \
3857d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    self.option.getOption("type") + " " + \
3867d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    self.option.getOption("element")
3877d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3887d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return script
3897d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3907d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3917d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Operator (Rule) :
3927d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """class implementing the operator concept
3937d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3947d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    An operator contains rules and other operators
3957d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    It is as rules propagated to all configuration children in parent descendants.
3967d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    It should only have the name ANY or ALL to be understood by PFW.
3977d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """
3987d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
3997d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "operator"
4007d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionNames = ["Name"]
4017d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(r"ANY|ALL").match
4027d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    childWhiteList = ["Rule", "Operator"]
4037d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4047d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    syntax = { "ANY" : "Any" , "ALL" : "All"}
4057d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4067d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def PFWSyntax (self, prefix=""):
4077d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """ return a pfw rule (ex : "Any{criterion1 is state1}") generated from "self" and its children options"""
4087d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        script = ""
4097d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4107d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        script += prefix + \
4117d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    self.syntax[self.getName()] + "{ "
4127d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4137d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        rules = self.extractChildrenByClass([Rule, Operator])
4147d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4157d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        PFWRules = []
4167d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for rule in rules :
4177d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            PFWRules.append(rule.PFWSyntax(prefix + "    "))
4187d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4197d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        script += (" , ").join(PFWRules)
4207d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4217d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        script += prefix + " }"
4227d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4237d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return script
4247d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4257d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ----------------------------------------------------------
4267d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4277d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Configuration (ElementWithRuleInheritance, ElementWithTag) :
4287d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "configuration"
4297d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionNames = ["Name"]
4307d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(r"conf *:").match
4317d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    childWhiteList = ["Rule", "Operator", "Path", "GroupPath"]
4327d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4337d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def composition (self, context):
4347d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """make all needed composition
4357d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4367d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Composition is the fact that group configuration with the same name defined
4377d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        in a parent will give their rule children to this configuration
4387d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """
4397d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4407d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        name = self.getName()
4417d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        sameNameConf = context.getConfigurations().getElementsFromName(name)
4427d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4437d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        sameNameConf.reverse()
4447d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4457d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for configuration in sameNameConf :
4467d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            # add same name configuration rule children to self child list
4477d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self.addChildren(configuration.extractChildrenByClass([Operator, Rule]), append=False)
4487d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4497d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4507d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def propagate (self, context=PropagationContext) :
4517d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """propagate proprieties to children
4527d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4537d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        make needed compositions, join ancestor name to its name,
4547d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        and add rules previously defined rules"""
4557d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4567d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # make all needed composition
4577d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.composition(context)
4587d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4597d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        super(Configuration, self).propagate(context)
4607d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4617d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def Inheritance (self, context) :
4627d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """make configuration name and rule inheritance"""
4637d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # check for configuration name inheritance
4647d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.OptionsInheritance(context)
4657d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4667d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # check for rule inheritance
4677d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.ruleInheritance(context)
4687d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4697d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def OptionsInheritance (self, context) :
4707d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """make configuration name inheritance """
4717d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4727d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        context.getConfigurationOptions().append(self.option.copy())
4737d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.setName(".".join(context.getConfigurationOptions().getOptionItems("Name")))
4747d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4757d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4767d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getRootPath (self) :
4777d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4787d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        paths = self.extractChildrenByClass([Path, GroupPath])
4797d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4807d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        rootPath = GroupPath()
4817d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        rootPath.addChildren(paths)
4827d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4837d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return rootPath
4847d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4857d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getConfigurableElements (self) :
4867d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return all path name defined in this configuration"""
4877d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4887d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self.getRootPath().getPathNames()
4897d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4907d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getRuleString(self):
4917d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """Output this configuration's rule as a string"""
4927d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4937d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # Create a rootRule
4947d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        ruleChildren = self.extractChildrenByClass([Rule, Operator])
4957d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
4967d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # Do not create a root rule if there is only one fist level Operator rule
4977d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if len(ruleChildren) == 1 and ruleChildren[0].__class__ == Operator :
4987d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            ruleroot = ruleChildren[0]
4997d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5007d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        else :
5017d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            ruleroot = Operator()
5027d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            ruleroot.setName("ALL")
5037d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            ruleroot.addChildren(ruleChildren)
5047d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5057d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return ruleroot.PFWSyntax()
5067d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5077d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def translate(self, translator):
5087d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        translator.createConfiguration(self.getName())
5097d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        translator.setRule(self.getRuleString())
5107d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5117d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        paths = self.extractChildrenByClass([Path, GroupPath])
5127d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        translator.setElementSequence(self.getConfigurableElements())
5137d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for path in paths:
5147d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            path.translate(translator)
5157d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5167d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def copy (self) :
5177d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return a shallow copy of the configuration"""
5187d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5197d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # create configuration or subclass copy
5207d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        confCopy = self.__class__()
5217d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5227d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # add children
5237d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        confCopy.children = list(self.children)
5247d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5257d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # add option
5267d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        confCopy.option = self.option.copy()
5277d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5287d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return confCopy
5297d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5307d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass GroupConfiguration (Configuration) :
5317d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "GroupConfiguration"
5327d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionNames = ["Name"]
5337d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(r"(supConf|confGroup|confType) *:").match
5347d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    childWhiteList = ["Rule", "Operator", "GroupConfiguration", "Configuration", "GroupPath"]
5357d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5367d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def composition (self, context) :
5377d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """add itself in context for configuration composition
5387d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5397d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Composition is the fact that group configuration with the same name defined
5407d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        in a parent will give their rule children to this configuration
5417d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """
5427d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5437d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # copyItself
5447d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        selfCopy = self.copy()
5457d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5467d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # make all needed composition
5477d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        super(GroupConfiguration, self).composition(context)
5487d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5497d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # add the copy in context for futur configuration composition
5507d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        context.getConfigurations().append(selfCopy)
5517d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5527d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5537d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getConfigurableElements (self) :
5547d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return a list. Each elements consist of a list of configurable element of a configuration
5557d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5567d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return a list consisting of all configurable elements for each configuration.
5577d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        These configurable elements are organized in a list"""
5587d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        configurableElements = []
5597d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5607d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        configurations = self.extractChildrenByClass([Configuration])
5617d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for configuration in configurations :
5627d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            configurableElements.append(configuration.getConfigurableElements())
5637d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5647d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        groudeConfigurations = self.extractChildrenByClass([GroupConfiguration])
5657d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for groudeConfiguration in groudeConfigurations :
5667d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            configurableElements += groudeConfiguration.getConfigurableElements()
5677d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5687d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return configurableElements
5697d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5707d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def translate(self, translator):
5717d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for child in self.extractChildrenByClass([Configuration, GroupConfiguration]):
5727d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            child.translate(translator)
5737d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5747d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ----------------------------------------------------------
5757d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5767d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Domain (ElementWithRuleInheritance, ElementWithTag) :
5777d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "domain"
5787d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    sequenceAwareKeyword = "sequenceAware"
5797d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5807d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(r"domain *:").match
5817d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    optionNames = ["Name", sequenceAwareKeyword]
5827d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    childWhiteList = ["Configuration", "GroupConfiguration", "Rule", "Operator"]
5837d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5847d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def propagate (self, context=PropagationContext) :
5857d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """ propagate name, sequenceAwareness and rule to children"""
5867d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5877d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # call the propagate method of all children
5887d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        super(Domain, self).propagate(context)
5897d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5907d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.checkConfigurableElementUnicity()
5917d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5927d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def Inheritance (self, context) :
5937d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """check for domain name, sequence awarness and rules inheritance"""
5947d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # check for domain name and sequence awarness inheritance
5957d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.OptionsInheritance(context)
5967d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
5977d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # check for rule inheritance
5987d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.ruleInheritance(context)
5997d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6007d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def OptionsInheritance(self, context) :
6017d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """ make domain name and sequence awareness inheritance
6027d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6037d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        join to the domain name all domain names defined in context and
6047d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if any domain in context is sequence aware, set sequenceAwareness to True"""
6057d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6067d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # add domain options to context
6077d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        context.getDomainOptions().append(self.option.copy())
6087d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6097d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # set name to the junction of all domain name in context
6107d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.setName(".".join(context.getDomainOptions().getOptionItems("Name")))
6117d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6127d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # get sequenceAwareness of all domains in context
6137d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        sequenceAwareList = context.getDomainOptions().getOptionItems(self.sequenceAwareKeyword)
6147d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # or operation on all booleans in sequenceAwareList
6157d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        sequenceAwareness = False
6167d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for sequenceAware in sequenceAwareList :
6177d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            sequenceAwareness = sequenceAwareness or sequenceAware
6187d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # current domain sequenceAwareness = sequenceAwareness
6197d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.option.setOption(self.sequenceAwareKeyword, sequenceAwareness)
6207d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6217d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6227d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def extractOptions(self, line) :
6237d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """Extract options from the definition line"""
6247d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        options = super(Domain, self).extractOptions(line)
6257d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6267d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        sequenceAwareIndex = self.optionNames.index(self.sequenceAwareKeyword)
6277d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6287d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # translate the keyword self.sequenceAwareKeyword if specified to boolean True,
6297d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # to False otherwise
6307d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        try :
6317d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            if options[sequenceAwareIndex] == self.sequenceAwareKeyword :
6327d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner               options[sequenceAwareIndex] = True
6337d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            else:
6347d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner               options[sequenceAwareIndex] = False
6357d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        except IndexError :
6367d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            options = options + [None] * (sequenceAwareIndex - len(options)) + [False]
6377d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return options
6387d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6397d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def getRootConfiguration (self) :
6407d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return the root configuration group"""
6417d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        configurations = self.extractChildrenByClass([Configuration, GroupConfiguration])
6427d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6437d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        configurationRoot = GroupConfiguration()
6447d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6457d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        configurationRoot.addChildren(configurations)
6467d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6477d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return configurationRoot
6487d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6497d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    # TODO: don't do that in the parser, let the PFW tell you that
6507d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def checkConfigurableElementUnicity (self):
6517d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """ check that all configurable elements defined in child configuration are the sames"""
6527d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6537d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # get a list. Each elements of is the configurable element list of a configuration
6547d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        configurableElementsList = self.getRootConfiguration().getConfigurableElements()
6557d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6567d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # if at least two configurations in the domain
6577d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if len(configurableElementsList) > 1 :
6587d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6597d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            # get first configuration configurable element list sort
6607d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            configurableElementsList0 = list(configurableElementsList[0])
6617d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            configurableElementsList0.sort()
6627d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6637d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            for configurableElements in configurableElementsList :
6647d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                # sort current configurable element list
6657d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                auxConfigurableElements = list(configurableElements)
6667d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                auxConfigurableElements.sort()
6677d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6687d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                if auxConfigurableElements != configurableElementsList0 :
6697d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    # if different, 2 configurations those not have the same configurable element list
6707d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    # => one or more configurable element is missing in one of the 2 configuration
6717d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    raise UndefinedParameter(self.getName())
6727d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6737d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6747d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def translate(self, translator):
6757d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        sequence_aware = self.option.getOption(self.sequenceAwareKeyword)
6767d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        translator.createDomain(self.getName(), sequence_aware)
6777d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6787d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        configurations = self.getRootConfiguration()
6797d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        configurableElementsList = configurations.getConfigurableElements()
6807d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6817d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # add configurable elements
6827d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if len(configurableElementsList) != 0 :
6837d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            for configurableElement in configurableElementsList[0] :
6847d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                translator.addElement(configurableElement)
6857d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6867d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        configurations.translate(translator)
6877d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6887d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass GroupDomain (Domain) :
6897d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "groupDomain"
6907d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    match = re.compile(r"(supDomain|domainGroup) *:").match
6917d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    childWhiteList = ["GroupDomain", "Domain", "GroupConfiguration", "Rule", "Operator"]
6927d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6937d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def translate(self, translator):
6947d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for child in self.extractChildrenByClass([Domain, GroupDomain]):
6957d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            child.translate(translator)
6967d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6977d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ----------------------------------------------------------
6987d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
6997d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Root(Element):
7007d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    tag = "root"
7017d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    childWhiteList = ["Domain", "GroupDomain"]
7027d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7037d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7047d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ===========================================
7057d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner""" Syntax error Exceptions"""
7067d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ===========================================
7077d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7087d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass MySyntaxProblems(SyntaxError) :
7097d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    comment = "syntax error in %(line)s "
7107d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7117d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__(self, line=None, num=None):
7127d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.setLine(line, num)
7137d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7147d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __str__(self):
7157d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7167d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if self.line :
7177d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self.comment = self.comment % {"line" : repr(self.line)}
7187d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if self.num :
7197d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            self.comment = "Line " + str(self.num) + ", " + self.comment
7207d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self.comment
7217d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7227d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def setLine (self, line, num):
7237d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.line = str(line)
7247d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.num = num
7257d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7267d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7277d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ---------------------------------------------------------
7287d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7297d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass MyPropagationError(MySyntaxProblems) :
7307d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """ Syntax error Exceptions used in the propagation step"""
7317d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    pass
7327d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7337d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass UndefinedParameter(MyPropagationError) :
7347d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    comment = "Configurations in domain '%(domainName)s' do not all set the same parameters "
7357d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__ (self, domainName):
7367d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.domainName = domainName
7377d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __str__ (self):
7387d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return self.comment % { "domainName" : self.domainName }
7397d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7407d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7417d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# -----------------------------------------------------
7427d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner""" Syntax error Exceptions used by parser"""
7437d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7447d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass MySyntaxError(MySyntaxProblems) :
7457d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """ Syntax error Exceptions used by parser"""
7467d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    pass
7477d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7487d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass MySyntaxWarning(MySyntaxProblems) :
7497d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """ Syntax warning Exceptions used by parser"""
7507d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    pass
7517d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7527d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass IndentationSyntaxError(MySyntaxError) :
7537d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    comment = """syntax error in %(line)s has no father element.
7547d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    You can only increment indentation by one tabutation per line")"""
7557d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7567d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass EmptyLineWarning(MySyntaxWarning):
7577d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    comment = "warning : %(line)s is an empty line and has been ommited"
7587d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7597d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass CommentWarning(MySyntaxWarning):
7607d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    comment = "warning : %(line)s is a commentary and has been ommited"
7617d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7627d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass ChildNotPermitedError(MySyntaxError):
7637d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__(self, line, fatherElement, childElement):
7647d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.comment = "syntax error in %(line)s, " + fatherElement.tag + " should not have a " + childElement.tag + " child."
7657d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        super(ChildNotPermitedError, self).__init__(line)
7667d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7677d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7687d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass UnknownElementTypeError(MySyntaxError):
7697d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    comment = " error in line %(line)s , not known element type were matched "
7707d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7717d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass SpaceInIndentationError(MySyntaxError):
7727d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    comment = " error in ,%(line)s space is not permited in indentation"
7737d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7747d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7757d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ============================================
7767d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner"""Class creating the DOM elements from a stream"""
7777d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner# ============================================
7787d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7797d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass ElementsFactory(object)  :
7807d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """Element factory, return an instance of the first matching element
7817d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7827d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    Test each element list in elementClass and instanciate it if it's methode match returns True
7837d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    The method match is called with input line as argument
7847d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """
7857d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__ (self):
7867d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.elementClass = [
7877d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        EmptyLine ,
7887d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Commentary,
7897d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        GroupDomain,
7907d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Domain,
7917d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Path,
7927d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        GroupConfiguration,
7937d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Configuration,
7947d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Operator,
7957d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Rule,
7967d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        GroupPath
7977d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        ]
7987d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
7997d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def createElementFromLine (self, line) :
8007d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return an instance of the first matching element
8017d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8027d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Test each element list in elementClass and instanciate it if it's methode match returns True
8037d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        The method match is called with the argument line.
8047d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        Raise UnknownElementTypeError if no element matched.
8057d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """
8067d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for element in self.elementClass :
8077d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            if element.match(line) :
8087d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                # print (line + element.__class__.__name__)
8097d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                return element(line)
8107d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # if we have not find any
8117d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        raise UnknownElementTypeError(line)
8127d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8137d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner#------------------------------------------------------
8147d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8157d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerclass Parser(object) :
8167d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    """Class implementing the parser"""
8177d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __init__(self):
8187d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.rankPattern = re.compile(r"^([\t ]*)(.*)")
8197d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.elementFactory = ElementsFactory()
8207d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.previousRank = 0
8217d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8227d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __parseLine__(self, line):
8237d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8247d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        rank, rest = self.__getRank__(line)
8257d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8267d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # instanciate the coresponding element
8277d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        element = self.elementFactory.createElementFromLine(rest)
8287d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8297d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.__checkIndentation__(rank)
8307d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8317d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return rank, element
8327d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8337d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __getRank__(self, line):
8347d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """return the rank, the name and the option of the input line
8357d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8367d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerthe rank is the number of tabulation (\t) at the line beginning.
8377d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagnerthe rest is the rest of the line."""
8387d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # split line in rank and rest
8397d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        rank = self.rankPattern.match(line)
8407d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if rank :
8417d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            rank, rest = rank.group(1, 2)
8427d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        else :
8437d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            raise MySyntaxError(line)
8447d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8457d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # check for empty line
8467d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if rest == "" :
8477d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            raise EmptyLineWarning(line)
8487d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8497d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        # check for space in indentation
8507d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if rank.find(" ") > -1 :
8517d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            raise SpaceInIndentationError(line)
8527d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8537d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        rank = len (rank) + 1  # rank starts at 1
8547d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8557d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8567d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return rank, rest
8577d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8587d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8597d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def __checkIndentation__(self, rank):
8607d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """check if indentation > previous indentation + 1. If so, raise IndentationSyntaxError"""
8617d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        if (rank > self.previousRank + 1) :
8627d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            raise IndentationSyntaxError()
8637d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        self.previousRank = rank
8647d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8657d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner    def parse(self, stream, verbose=False):
8667d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        """parse a stream, usually a opened file"""
8677d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        myroot = Root("root")
8687d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        context = [myroot]  # root is element of rank 0
8697d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        warnings = ""
8707d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8717d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        for num, line in enumerate(stream):
8727d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            try:
8737d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                rank, myelement = self.__parseLine__(line)
8747d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8757d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                while len(context) > rank :
8767d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    context.pop()
8777d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                context.append(myelement)
8787d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                context[-2].addChild(myelement)
8797d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8807d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            except MySyntaxWarning, ex:
8817d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                ex.setLine(line, num + 1)
8827d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                if verbose :
8837d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                    print >>sys.stderr, ex
8847d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8857d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner            except MySyntaxError, ex :
8867d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                ex.setLine(line, num + 1)
8877d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner                raise
8887d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
8897d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner        return myroot
8907d996811c0e80b30a40a5add1f01f0314f2ebef4David Wagner
891