<filename>Vault7/Lost-in-Translation/windows/Resources/Ops/PyScripts/lib/ops/ActionFramework.py<gh_stars>10-100

import util.DSZPyLogger as logging
import re
import xml.etree.ElementTree
from Queue import Queue
acfwlog = logging.getLogger('ActionFramework')
acfwlog.setFileLogLevel(logging.WARNING)

class Forest(object, ):

    def __init__(self, trees=None):
        self.trees = (trees or [])

    def __len__(self):
        return len(self.trees)

    def addTree(self, tree):
        self.trees.append(tree)
        acfwlog.debug('added new tree, trees: {0}'.format(self.trees))

    def printTrees(self):
        map(self.__printNodes, self.trees)

    def __printNodes(self, node, level=1):
        print '{0:-<{1}} {2}'.format(' ', level, node)
        for child in node.children:
            self.__printNodes(child, (level + 1))

    def getiterator(self):
        allnodes = []
        for tree in self.trees:
            allnodes.extend(tree.getiterator())
        return allnodes

class TreeItem(object, ):

    def __init__(self, parent=None, children=set([])):
        acfwlog.debug('New Treeitem: s:{2},p:{0},c:{1}'.format(parent, children, self))
        self.parent = parent
        self.children = set([])
        self.addChildren(children)
        if parent:
            parent.addChild(self)

    def addChildren(self, children):
        for child in children:
            self.addChild(child)

    def addChild(self, child):
        acfwlog.debug('Adding a child: p:{0},c:{1}'.format(self, child))
        child.parent = self
        self.children.add(child)

    def getiterator(self):
        allnodes = []
        allnodes.append(self)
        for child in self.children:
            allnodes.extend(child.getiterator())
        return allnodes

class ValidationFailure(object, ):

    def __init__(self, act, msg):
        assert isinstance(act, Action)
        self.act = act
        self.msg = msg
        self.at = None

    def AddAttribute(self, at):
        self.at = at

    def __repr__(self, *args, **kwargs):
        repout = 'Attribute: {0}\nAction: {1}\nMessage: {2}'.format(self.at, self.act, self.msg)
        return repout

class AttributePackage(TreeItem, ):

    def __init__(self, attribname, attribval=None, actmgr=None, attribconfig=False, attribdisplay=None, attribdefault=None, **kwargs):
        self.attribname = attribname
        self.attribval = attribval
        self.attribconfig = attribconfig
        self.attribdisplay = (attribdisplay or self.attribname)
        self.attribdefault = attribdefault
        self.actmgr = actmgr
        self.valid = False
        TreeItem.__init__(self, **kwargs)

    def Validate(self):
        validationfailures = []
        validationfailures.extend(self.actmgr.Validate())
        for fail in validationfailures:
            fail.AddAttribute(self)
        for child in self.children:
            validationfailures.extend(child.Validate())
        return validationfailures

    def Execute(self):
        self.valid = self.actmgr.Execute()
        if ((not self.valid) and (self.attribdefault is not None)):
            self.attribval = self.attribdefault
            self.valid = True
        if self.valid:
            if ('%' in self.attribval):
                self.attribval = re.sub('%(.+)%', (lambda m: ('%%{0}%%'.format(m.group(1)) if (self.actmgr.GetActionVar(m.group(1)) is None) else self.actmgr.GetActionVar(m.group(1)))), self.attribval)
            for child in self.children:
                child.Execute()
        return self.valid

    def __str__(self, *args, **kwargs):
        return '<Attribute Package -- Name: {0} Value: {1} Config: {2} Display: {3}>'.format(str(self.attribname), str(self.attribval), str(self.attribconfig), str(self.attribdisplay))

    def __unicode__(self, *args, **kwargs):
        return u'<Attribute Package -- Name: {0} Value: {1} Config: {2} Display: {3}>'.format(self.attribname, self.attribval, self.attribconfig, self.attribdisplay)

    def __repr__(self, *args, **kwargs):
        return '<Attribute Package -- Name: {0} Value: {1} Config: {2} Display: {3}>'.format(repr(self.attribname), repr(self.attribval), repr(self.attribconfig), repr(self.attribdisplay))

class ActionDataSource(object, ):

    def __init__(self, rootActions=[], **kwargs):
        self.rootActs = rootActions

    def GetRootActions(self):
        return self.rootActs

class XMLAttributeActionDataSource(ActionDataSource, ):

    def __init__(self, xmlactions, xmltoattributemap):
        self.xmlacts = xmlactions
        acfwlog.debug('XMLActions: {0}'.format(xmlactions))
        self.actionmap = xmltoattributemap
        self.atpkg = self._buildActPkgs(xmlactions)
        ActionDataSource.__init__(self, [self.atpkg])

    def __getActionsAttributes(self, act, attriblist):
        params = act.mandatoryparams[:]
        params.extend(act.optionalparams)
        strippedattribs = {}
        for param in params:
            try:
                if (param in attriblist):
                    acfwlog.debug('Removing this attribute: {0}'.format(param))
                    strippedattribs[param] = attriblist.pop(param)
            except:
                acfwlog.debug('Removing attrib failed.', exc_info=True)
        return strippedattribs

    def _buildActPkgs(self, element, parent=None):
        acfwlog.debug('Building AttributePackage for element: {0}'.format(element))
        actions = []
        try:
            attriblist = element.attrib.copy()
            attribvalue = attriblist.pop('value')
            attribconfig = (attriblist.pop('config', 'false').lower() == 'true')
            attribdisplay = attriblist.pop('display', None)
            attribdefault = attriblist.pop('default', None)
            for param in element.attrib:
                if (not (param in attriblist)):
                    continue
                try:
                    actklass = self.actionmap[param.lower()]
                    actparams = self.__getActionsAttributes(actklass, attriblist)
                except:
                    acfwlog.debug('no map for param {0}'.format(param))
                    continue
                currentact = actklass(actparams, parent=None)
                actions.append(currentact)
        except:
            acfwlog.error('Error while processing element. See OPLOGS for more info.', exc_info=True)
            acfwlog.debug(xml.etree.ElementTree.dump(element))
            return None
        actmgr = ActionManager(actions)
        atpkg = AttributePackage(attribname=element.tag, attribval=attribvalue, attribconfig=attribconfig, attribdisplay=attribdisplay, attribdefault=attribdefault, actmgr=actmgr, parent=parent)
        for childelem in element.getchildren():
            child = self._buildActPkgs(childelem, atpkg)
            if (child is not None):
                atpkg.addChild(child)
        return atpkg

class XMLActionDataSource(ActionDataSource, ):

    def __init__(self, xmlactions, xmltoattributemap, **kwargs):
        self.xmlacts = xmlactions
        acfwlog.debug('XMLActions: {0}'.format(xmlactions))
        self.actionmap = xmltoattributemap
        actTree = self.buildActionTree(xmlactions, **kwargs)
        ActionDataSource.__init__(self, actTree, **kwargs)

    def buildActionTree(self, element, parent=None, **kwargs):
        acfwlog.debug('Building Action tree.')
        try:
            actklass = self.actionmap[element.tag.lower()]
        except:
            return []
        acttree = []
        actparams = element.attrib
        currentact = actklass(actparams, parent)
        acttree.append(currentact)
        for subactel in element.getchildren():
            acttree.append(self.__buildActionTree(subactel, currentact))
        return acttree

class XMLConditionalActionDataSource(XMLActionDataSource, ):

    def __init__(self, xmlactions, xmltoattributemap, conditionalobjs):
        self.conditionalobjs = (conditionalobjs if (type(conditionalobjs) is list) else [conditionalobjs])
        XMLActionDataSource.__init__(self, xmlactions, xmltoattributemap, conditionalobjs=self.conditionalobjs)

    def buildActionTree(self, element, parent=None, conditionalobjs=[], **kwargs):
        acfwlog.debug('XMLCond - Building Action tree for element: {0}'.format(element))
        acttree = []
        acfwlog.debug('cond objs: {0}'.format(conditionalobjs))
        applicableconobjs = conditionalobjs[:]
        currentact = None
        try:
            if (element.tag.lower() in self.actionmap):
                actklass = self.actionmap[element.tag.lower()]
                actparams = element.attrib
                currentact = actklass(actparams, parent=parent)
                if (len(conditionalobjs) > 0):
                    currentact.additionaldata = conditionalobjs[0]
                else:
                    currentact.additionaldata = None
                if parent:
                    parent.addChild(currentact)
                acttree.append(currentact)
            else:
                attriblist = element.attrib.copy()
                attribname = element.tag.lower()
                attribvalue = attriblist.pop('value')
                acfwlog.debug('attribname,val: {0},{1}'.format(attribname, attribvalue))
                applicableconobjs = filter((lambda x: (x.__dict__.has_key(attribname) and (x.__dict__[attribname] == attribvalue))), applicableconobjs)
        except:
            acfwlog.error('Error while processing element. See OPLOGS for more info.', exc_info=True)
            acfwlog.debug(xml.etree.ElementTree.dump(element))
            return []
        acfwlog.debug('appcond objs: {0}'.format(applicableconobjs))
        for subactel in element.getchildren():
            acttree.extend(self.buildActionTree(subactel, conditionalobjs=applicableconobjs))
        return acttree

class ProcessableAction(object, ):

    def __init__(self, processparams):
        self.mandatoryprocessparams = processparams

    def process(self):
        raise NotImplementedError('Subclass must implement this.')

    def validateprocess(self, params):
        for mandatoryparam in self.mandatoryprocessparams:
            if (params.get(mandatoryparam) is None):
                return False
        return True

    def isprocparam(self, param):
        return (param in self.mandatoryprocessparams)

class Action(TreeItem, ):
    mandatoryparams = []
    optionalparams = []
    validparamvalues = {}

    def __init__(self, execparams, **kwargs):
        TreeItem.__init__(self, **kwargs)
        self.actmgr = None
        self.execparams = execparams
        self.additionaldata = None
        self.done = False
        if (self.mandatoryparams is None):
            self.mandatoryparams = []
        if (self.optionalparams is None):
            self.optionalparams = []
        for param in self.mandatoryparams:
            setattr(self, param, None)
        for param in self.optionalparams:
            setattr(self, param, None)
        acfwlog.debug('action {0}:'.format(self))

    def RegisterAM(self, actmgr):
        self.actmgr = actmgr

    def Execute(self):
        acfwlog.debug('{0} is executing'.format(self.__class__))
        acfwlog.debug('My execparams: {0}'.format(self.execparams))
        self.done = True

    def Validate(self):
        validfails = []
        acfwlog.debug('Validating {0}'.format(self))
        for manparam in self.mandatoryparams:
            if (not (manparam in self.execparams.keys())):
                validfails.append(ValidationFailure(self, 'Failed Validation! MANDATORY parameter missing: {0}'.format(manparam)))
        for param in self.execparams.keys():
            if ((not (param in self.optionalparams)) and (not (param in self.mandatoryparams))):
                validfails.append(ValidationFailure(self, 'Failed Validation! This parameter is not a mandatory or optional parameter: {0}'.format(param)))
            elif ((param in self.validparamvalues.keys()) and (not (self.execparams[param] in self.validparamvalues[param]))):
                validfails.append(ValidationFailure(self, "Failed Validation! This parameter's value is not a valid value. Please ensure the value is one of the following:\nParam: {0}\nValue: {1}\nValid Values: {2}".format(param, self.execparams[param], self.validparamvalues[param])))
        return validfails

    def GetVariable(self, varname):
        if self.parent:
            return self.parent.GetVariable(varname)
        return None

    def FindParamHandler(self, param):
        if ((param in self.mandatoryparams) or (param in self.optionalparams)):
            return self
        elif (not (self.parent is None)):
            return self.parent.FindParamHandler(param)
        else:
            return None

    def GetLastResult(self):
        if getattr(self, 'result', None):
            return self.result
        elif (not (self.parent is None)):
            return self.parent.GetLastResult()
        else:
            return None

    def __repr__(self):
        return '<{0} {1}>'.format(type(self), [(x, self.__dict__[x]) for x in filter((lambda x: (not (x.startswith('__') or (x == 'parent') or (x == 'children')))), self.__dict__)])

class ProcessAction(Action, ):

    def __init__(self, params, parent):
        Action.__init__(self, execparams=params, parent=parent)

    def Execute(self):
        Action.Execute(self)
        return None

    def Validate(self):
        Action.Validate(self)
        return ValidationFailure(self, 'This action is not implemented')

class AttributePackageManager(Forest, ):

    def __init__(self):
        Forest.__init__(self)
        self.valid = False

    def walkAndCollect(self, procfunc):
        q = Queue()
        repolist = [{}]
        for pkg in self.trees:
            if pkg.valid:
                q.put(pkg)
        while (not q.empty()):
            atpkg = q.get_nowait()
            procfunc(atpkg, repolist)
            for child in atpkg.children:
                if child.valid:
                    q.put_nowait(child)
        return repolist

    def addAttributePackage(self, atpkg):
        try:
            results = atpkg.Validate()
            if (len(results) == 0):
                self.addTree(atpkg)
                valid = True
                self.valid = valid
            else:
                acfwlog.critical('Your attribute package failed validation.  Please review the results and fix as needed.\n{0}'.format(results))
                return False
        except:
            acfwlog.critical('Unhandled exception!', exc_info=True)
        return self.valid

    def GetResults(self):

        def cbfunc(atpkg, repolist):
            if (atpkg.name not in repolist):
                repolist[atpkg.attribname] = atpkg
        dicts = self.walkAndCollect(cbfunc)
        return dicts

    def Execute(self):
        for atpkg in self.trees:
            atpkg.Execute()

class ActionManager(Forest, ):

    def __init__(self, actions):
        Forest.__init__(self, trees=actions)
        for act in self.getiterator():
            act.RegisterAM(self)

    def ParentAction(self, act):
        return act.parent

    def Execute(self):
        return all(map(self.__execute, self.trees))

    def GetActionVar(self, varname):
        varvalue = None
        for act in self.getiterator():
            varvalue = act.GetVariable(varname)
            if varvalue:
                break
        return varvalue

    def GetActionResults(self, actklass=Action):
        acts = filter((lambda x: (isinstance(x, actklass) and x.done)), self.getiterator())
        try:
            return [act.result for act in acts]
        except:
            acfwlog.critical('Unhandled exception in GetActionResults. See log for more informaiton.', exc_info=True)
            return []

    def Validate(self):
        allacts = self.getiterator()
        acfwlog.debug('allacts,trees {0},{1}'.format(allacts, self.trees))
        results = []
        for act in allacts:
            results.extend(act.Validate())
        acfwlog.debug('ActMgr Validate results: {0}'.format(results))
        return results

    def __execute(self, act):
        try:
            suc = act.Execute()
        except:
            acfwlog.critical('Unexpected Error while executing action: {0}'.format(act), exc_info=True)
            suc = False
        if suc:
            acfwlog.debug('This actions children: {0}'.format(act.children))
            for child in act.children:
                suc = self.__execute(child)
        return suc

class ActionParameter(object, ):
    pass

class ActionParamterGroup(ActionParameter, ):

    def __init__(self, grpname):
        self.name = grpname
        self.params = []

    def add(self, actionparam):
        self.params.append(actionparam)