configurationengine/source/cone/public/rules.py
author m2lahtel
Tue, 10 Aug 2010 14:29:28 +0300
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
permissions -rw-r--r--
ConE 1.2.11 release
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     1
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     2
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     3
# All rights reserved.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     4
# This component and the accompanying materials are made available
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     5
# under the terms of "Eclipse Public License v1.0"
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     6
# which accompanies this distribution, and is available
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     7
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     8
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     9
# Initial Contributors:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    10
# Nokia Corporation - initial contribution.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    11
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    12
# Contributors:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    13
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    14
# Description: 
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    15
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    16
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    17
import operator as ops
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    18
import logging
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    19
import tokenize
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    20
import re
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    21
from token import ENDMARKER, NAME, ERRORTOKEN, OP
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    22
import StringIO
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    23
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    24
from cone.public import container, exceptions, utils
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    25
import types
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    26
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    27
RELATIONS = {}
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    28
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    29
def abstract():
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    30
    import inspect
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    31
    caller = inspect.getouterframes(inspect.currentframe())[1][3]
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    32
    raise NotImplementedError(caller + ' needs to be implemented')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    33
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    34
REF_DOLLAR = '$'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    35
REF_START_BRACE = '{'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    36
REF_END_BRACE = '}'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    37
REF_REGEX = re.compile('(?P<ref>\${[\w\.\*]*})', re.UNICODE)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    38
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    39
def get_tokens(tokenstr):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    40
    result = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    41
    tokens = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    42
    tokenstr = tokenstr.replace('\r', '')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    43
    name_buffer = [] # Temp buffer for reading name tokens
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    44
    last_epos = None
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    45
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    46
    ref_start = False
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    47
    for toknum, tokval, spos, epos, _  in tokenize.generate_tokens(StringIO.StringIO(unicode(tokenstr)).readline):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    48
        val = tokval.strip('\r\n\t ')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    49
        
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    50
        if toknum == ENDMARKER and name_buffer:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    51
            tokens.append(''.join(name_buffer))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    52
        
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    53
        # Ignore whitespace (this ignores also the end marker,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    54
        # since its value is empty)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    55
        if val == '': continue
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    56
        
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    57
        # Handle the references here, ${ref} is the format
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    58
        if toknum in (OP, ERRORTOKEN) and\
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    59
                tokval in (REF_DOLLAR, REF_START_BRACE, REF_END_BRACE) or\
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    60
                ref_start:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    61
            if tokval == REF_DOLLAR:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    62
                ref_start = True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    63
            elif tokval == REF_END_BRACE:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    64
                ref_start = False
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    65
            if name_buffer and spos[1] != last_epos[1]:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    66
                tokens.append(''.join(name_buffer))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    67
                name_buffer = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    68
            name_buffer.append(tokval)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    69
            last_epos = epos
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    70
        # Put NAME, and ERRORTOKEN tokens through the temp
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    71
        # buffer
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    72
        elif toknum in (NAME, ERRORTOKEN):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    73
            # If this and the previous token in the temp buffer are not adjacent,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    74
            # they belong to separate tokens
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    75
            if name_buffer and spos[1] != last_epos[1]:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    76
                tokens.append(''.join(name_buffer))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    77
                name_buffer = []
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
    78
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    79
            name_buffer.append(val)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    80
            last_epos = epos
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    81
        # Other tokens can just go directly to the token list
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    82
        else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    83
            if name_buffer:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    84
                tokens.append(''.join(name_buffer))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    85
                name_buffer = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    86
            tokens.append(val)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    87
    
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    88
    while len(tokens) > 0:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    89
        val = tokens.pop(0)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    90
        # Join the refs with dot in between them to make them dotted refs
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    91
        if val == '.':
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    92
            newval = ".".join([result.pop(),tokens.pop(0)])
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    93
            result.append( newval )
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    94
        else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    95
            result.append( val )
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    96
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    97
    return result
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    98
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    99
class RelationException(Exception):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   100
    pass
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   101
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   102
#### The containers are here ####
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   103
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   104
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   105
class RelationBase(object):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   106
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   107
    RelationBase defines a base class for all named relations that can be applied between objects. 
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   108
    e.g. Relation depends, that can be applied in Rule
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   109
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   110
    relation_name = "RelationBase"
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   111
    def __init__(self, data, left, right):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   112
        self.description = ""
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   113
        self.ref = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   114
        self.lineno = None
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   115
        self.data = data or container.DataContainer()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   116
        self.left = left
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   117
        self.right = right
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   118
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   119
    def __str__(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   120
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   121
        @return: A string presentation of the relation object
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   122
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   123
        return "%s %s %s" % (self.left,self.relation_name,self.right)
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   124
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   125
    def __repr__(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   126
        return "%s(ref=%r, lineno=%r)" % (self.__class__.__name__, self.ref, self.lineno)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   127
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   128
    def get_name(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   129
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   130
        @return: The relation name.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   131
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   132
        return self.relation_name
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   133
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   134
    def get_description(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   135
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   136
        @return: a possible description of the relation.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   137
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   138
        return self.description
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   139
        
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   140
    def execute(self, context=None):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   141
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   142
        Execute the relation object.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   143
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   144
        pass
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   145
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   146
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   147
class RelationContainer(RelationBase, list):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   148
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   149
    This class provides the RelationContainer interface for collecting
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   150
    relation sets into one place which can be executed through the container.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   151
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   152
    def __init__(self, data=None):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   153
        super(RelationContainer, self).__init__(data, 'LContainer', 'RContainer')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   154
        self.value_list = list()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   155
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   156
    def append(self, value):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   157
        self.value_list.append(value)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   158
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   159
    def __iter__(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   160
        return self.value_list.__iter__()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   161
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   162
    def __len__(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   163
        return len(self.value_list)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   164
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   165
    def __or__(self, other):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   166
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   167
        This function adds two RelationContainers to each other and removes
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   168
        duplicates from the result.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   169
        The modification is inplace and the returned value is called object.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   170
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   171
        self.value_list = set(self.value_list) | set(other.value_list)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   172
        return self
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   173
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   174
    def __unicode__(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   175
        if self:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   176
            ret = ''
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   177
            for value in self:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   178
                ret += unicode(value)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   179
        else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   180
            ret = 'No relations'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   181
        return ret
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   182
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   183
    def find_relations(self, refs): abstract()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   184
    def add_relation(self, relation): abstract()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   185
    def has_errors(self): abstract()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   186
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   187
class RelationContainerImpl(RelationContainer):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   188
    """ Base implementation for RelationContainer to use in ConE rules
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   189
    """
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   190
    def execute(self, context=None):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   191
        ret = True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   192
        i = 0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   193
        for relation in self:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   194
            i += 1
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   195
            r = relation.execute(context)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   196
            ret = ret and r
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   197
        return ret
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   198
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   199
    def find_relations(self, refs):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   200
        relations = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   201
        for ref in refs:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   202
            for relation in self:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   203
                if relation.has_ref(ref):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   204
                    relations.append(relation)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   205
        return relations
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   206
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   207
    def add_relation(self, relation):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   208
        self.append(relation)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   209
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   210
    def has_ref(self, refs):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   211
        for ref in refs:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   212
            for relation in self:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   213
                if relation.has_ref(ref):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   214
                    return True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   215
        return False
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   216
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   217
    def has_errors(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   218
        for relation in self:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   219
            if relation.has_errors():
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   220
                return True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   221
        return False
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   222
            
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   223
    def get_errors(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   224
        errors = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   225
        for relation in self:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   226
            errors += relation.get_errors()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   227
        return errors
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   228
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   229
#### The relations are here ####
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   230
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   231
class BaseRelation(RelationBase):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   232
    """ BaseRelation implements the basic evaluation logic for relations
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   233
    This class abstract and should be extended for concrete implementation of
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   234
    relation type.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   235
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   236
    Subclasses need to set their own context in their constructor before this
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   237
    class's constructor is called if custom context is needed. If context not
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   238
    set then DefaultContext is used.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   239
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   240
    KEY = 'base_relation'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   241
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   242
    def __init__(self, data, left, right):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   243
        # Context needs to be overridden for special purposes
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   244
        try:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   245
            self.__getattribute__('context')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   246
        except AttributeError:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   247
            self.context = DefaultContext(data)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   248
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   249
        left = self.expand_rule_elements(left)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   250
        right = self.expand_rule_elements(right)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   251
        super(BaseRelation, self).__init__(data, left, right)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   252
        self.interpreter = ASTInterpreter(context=self.context)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   253
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   254
    def execute(self, context=None):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   255
        """
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   256
        @param context: The context for execution can be given as a parameter. 
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   257
        @return Returns error dictionary
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   258
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   259
        In the client code proper way to check if the rule applies:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   260
        info = relation.execute()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   261
        if not info.has_errors():
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   262
        else: HANDLE ERRORS
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   263
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   264
        # logger.debug("Interpreter context %s" % self.interpreter.context)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   265
        self.interpreter.create_ast('%s %s %s' % (self.left, self.KEY, self.right))
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   266
        ret = self.interpreter.eval(context, relation=self)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   267
        return ret
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   268
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   269
    def get_keys(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   270
        """ Returns the references from this relation.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   271
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   272
        refs = ASTInterpreter.extract_refs(self.left)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   273
        refs += ASTInterpreter.extract_refs(self.right)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   274
        return refs
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   275
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   276
    def has_ref(self, ref):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   277
        """ Returns if the 'ref' is included in this relation
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   278
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   279
        return ref in self.get_keys()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   280
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   281
    def has_errors(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   282
        return bool(self.interpreter.errors)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   283
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   284
    def get_refs(self):
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   285
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   286
        Get a list of left side references and right side references.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   287
        @return: left refs
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   288
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   289
        try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   290
            refs = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   291
            tempast = ASTInterpreter()
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   292
            tempast.create_ast("%s" % self.left)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   293
            for exp in tempast.expression_list:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   294
                refs += exp.get_refs()
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   295
        except Exception, e:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   296
            utils.log_exception(logging.getLogger('cone.rules'), "Exception in get_refs() of relation %r: %s" % (self, e))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   297
            return []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   298
        return refs
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   299
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   300
    def get_set_refs(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   301
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   302
        Get a list of references that could get altered by set expression in this rule. 
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   303
        This list is empty if the relation does not have any set expressions.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   304
        @return: a list of references.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   305
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   306
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   307
        return [exp.left.get_ref() for exp in self.get_set_expressions()]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   308
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   309
    def get_expressions(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   310
        if not self.interpreter.expression_list:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   311
            self.interpreter.create_ast('%s %s %s' % (self.left, self.KEY, self.right))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   312
        return self.interpreter.expression_list
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   313
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   314
    def get_set_expressions(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   315
        setelems = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   316
        if not self.interpreter.expression_list:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   317
            self.interpreter.create_ast('%s %s %s' % (self.left, self.KEY, self.right))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   318
        for elem in self.interpreter.expression_list:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   319
            if isinstance(elem, SetExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   320
                setelems.append(elem)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   321
        return setelems
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   322
        
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   323
    def _eval_rside_value(self, value): abstract()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   324
    def _compare_value(self, value): abstract()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   325
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   326
    def extract_erroneus_features_with_values(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   327
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   328
        Extract references who have errors.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   329
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   330
        Returns dictionary { 'reference' : 'value' }
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   331
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   332
        data_dict = {}
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   333
        for ref in ASTInterpreter.extract_refs(self.right):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   334
            value = self.data.get_feature(ref)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   335
            if self._compare_value(value):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   336
                data_dict[ref] = value
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   337
            elif value == None:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   338
                data_dict[ref] = None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   339
        return data_dict
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   340
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   341
    def get_errors(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   342
        return self.interpreter.errors
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   343
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   344
    def expand_rule_elements(self, rule):
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   345
        """ Expands rule elements base on the reference.
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   346
        Context is used for fetching the child elements for parent references
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   347
        which uses asterisk identifier for selecting all child features: 
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   348
        'parent_feature.*' -> 'child_fea_1 and child_fea_2'.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   349
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   350
        tokens = get_tokens(rule) # [token for token in rule.split()]
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   351
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   352
        expanded_rule = ""
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   353
        for token in tokens:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   354
            if token.endswith('.*'):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   355
                index = token.index('.*')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   356
                parent_ref = token[:index]
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   357
                children = self.context.get_children_for_reference(parent_ref)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   358
                expanded_element = ' and '.join([child.reference for child in children])
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   359
                if expanded_rule:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   360
                    expanded_rule = '%s and %s' % (expanded_rule, expanded_element.rstrip())
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   361
                else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   362
                    expanded_rule = expanded_element.rstrip()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   363
            elif token.lower() in OPERATORS:
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   364
                operator_class = OPERATORS[token]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   365
                if operator_class.PARAM_COUNT == 2:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   366
                    expanded_rule += ' %s ' % token
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   367
                else:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   368
                    expanded_rule += '%s ' % token
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   369
            else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   370
                if expanded_rule:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   371
                    expanded_rule += '%s'% token
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   372
                else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   373
                    expanded_rule = token
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   374
        return expanded_rule.strip()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   375
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   376
class RequireRelation(BaseRelation):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   377
    KEY = 'requires'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   378
RELATIONS[RequireRelation.KEY] = RequireRelation
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   379
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   380
class ExcludesRelation(BaseRelation):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   381
    KEY = 'excludes'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   382
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   383
RELATIONS['excludes'] = ExcludesRelation
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   384
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   385
################################
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   386
# Abstract syntax tree builder #
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   387
################################
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   388
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   389
def nor(expression, a, b):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   390
    return not ops.or_(a, b)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   391
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   392
def nand(expression, a, b):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   393
    return not ops.and_(a, b)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   394
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   395
def truth_and(expression, a, b):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   396
    return ops.truth(a) and ops.truth(b)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   397
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   398
class DefaultContext(object):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   399
    """ DefaultContext implements ConE specific context for handling rules
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   400
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   401
    def __init__(self, data):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   402
        self.data = data
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   403
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   404
    def eval(self, ast, expression, value):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   405
        pass
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   406
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   407
    def set(self, expression, value):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   408
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   409
        set a element described with expression to value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   410
        @param expression: the expression refering to a element 
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   411
        @param value:  the value to set 
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   412
        @raise exception: when the setting value to expression fails.  
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   413
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   414
        pass
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   415
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   416
    def get_children_for_reference(self, reference):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   417
        # implement ConE specific children expansion
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   418
        pass
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   419
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   420
    def convert_value(self, value):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   421
        if value in ('True', 'true', '1'):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   422
            return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   423
        elif value in ('False', 'false', '0'):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   424
            return False
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   425
        elif value in ('None',):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   426
            return None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   427
        else:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   428
            try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   429
                return int(value)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   430
            except:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   431
                return value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   432
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   433
    def handle_terminal(self, expression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   434
        try:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   435
            return int(expression)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   436
        except:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   437
            return expression
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   438
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   439
PRECEDENCES = {
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   440
    'PREFIX_OPERATORS' : 10,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   441
    'MULDIV_OPERATORS' : 8,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   442
    'ADDSUB_OPERATORS' : 7,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   443
    'SHIFT_OPERATORS' : 6,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   444
    'BITWISE_OPERATORS' : 5,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   445
    'COMPARISON_OPERATORS' : 4,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   446
    'SET_OPERATORS' : 3,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   447
    'BOOLEAN_OPERATORS' : 2, 
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   448
    'RELATION_OPERATORS' : 1,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   449
    'NOT_DEFINED' : 0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   450
}
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   451
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   452
class Expression(object):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   453
    PRECEDENCE = PRECEDENCES['NOT_DEFINED']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   454
    KEY = 'base_expression'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   455
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   456
    def __init__(self, ast):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   457
        self.ast = ast
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   458
        self.value = None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   459
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   460
    def get_title(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   461
        return self.KEY
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   462
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   463
    def is_terminal(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   464
        return False
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   465
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   466
    def eval(self, context, **kwargs): pass
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   467
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   468
    def get_refs(self): return []
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   469
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   470
class OneParamExpression(Expression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   471
    PARAM_COUNT = 1
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   472
    # OP that return itself 
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   473
    OP = lambda _, x : x
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   474
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   475
    def __init__(self, ast, expression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   476
        super(OneParamExpression, self).__init__(ast)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   477
        self.expression = expression
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   478
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   479
    def __unicode__(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   480
        return u'%s %s' % (self.KEY, self.expression)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   481
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   482
    def __str__(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   483
        return '%s %s' % (self.KEY, self.expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   484
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   485
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   486
        self.value = self.OP(self.expression.eval(context)) 
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   487
        context.eval(self.ast, self, self.value)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   488
        return self.value
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   489
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   490
class TwoOperatorExpression(Expression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   491
    PARAM_COUNT = 2
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   492
    OP = None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   493
    EVAL_AS_BOOLS = True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   494
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   495
    def __init__(self, ast, left, right):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   496
        super(TwoOperatorExpression, self).__init__(ast)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   497
        self.left = left
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   498
        self.right = right
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   499
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   500
    def __unicode__(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   501
        return u'%s %s %s' % (self.left, self.KEY, self.right)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   502
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   503
    def __str__(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   504
        return '%s %s %s' % (self.left, self.KEY, self.right)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   505
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   506
    def eval(self, context, **kwargs):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   507
        self.value = self.OP(self.left.eval(context), self.right.eval(context))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   508
        context.eval(self.ast, self, self.value)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   509
        return self.value
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   510
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   511
class TwoOperatorBooleanExpression(TwoOperatorExpression):
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   512
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   513
        self.value = self.OP(bool(self.left.eval(context, **kwargs)), bool(self.right.eval(context, **kwargs)))
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   514
        context.eval(self.ast, self, self.value)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   515
        return self.value         
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   516
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   517
class ReferenceTerminal(Expression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   518
    PARAM_COUNT = 0
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   519
    KEY = 'reference'
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   520
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   521
    def __init__(self, ast, expression):
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   522
        super(ReferenceTerminal, self).__init__(ast)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   523
        if not ASTInterpreter.is_ref(unicode(expression)):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   524
            expression = ASTInterpreter.create_ref(expression)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   525
        self.expression = expression
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   526
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   527
    def is_terminal(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   528
        return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   529
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   530
    def eval(self, context, **kwargs):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   531
        """ Use context to eval the value
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   532
        Expression on ReferenceTerminal is feature reference or value
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   533
        context should handle the reference conversion to correct value
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   534
        """
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   535
        self.value = context.handle_terminal(ASTInterpreter.clean_ref(self.expression))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   536
        return self.value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   537
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   538
    def get_ref(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   539
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   540
        @return: The setting reference, e.g. 'MyFeature.MySetting'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   541
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   542
        return ASTInterpreter.clean_ref(self.expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   543
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   544
    def get_refs(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   545
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   546
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   547
        return [u'%s' % self.get_ref()]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   548
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   549
    def __unicode__(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   550
        return self.expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   551
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   552
    def __str__(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   553
        return "(%s => %s)" % (self.expression, self.value)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   554
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   555
    def __repr__(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   556
        return self.expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   557
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   558
class ValueTerminal(Expression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   559
    PARAM_COUNT = 0
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   560
    KEY = 'value_terminal'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   561
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   562
    def __init__(self, ast, expression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   563
        super(ValueTerminal, self).__init__(ast)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   564
        self.expression = expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   565
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   566
    def is_terminal(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   567
        return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   568
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   569
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   570
        self.value = context.convert_value(self.expression)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   571
        return self.value
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   572
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   573
    def __unicode__(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   574
        return self.expression
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   575
    
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   576
    def __str__(self):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   577
        return self.expression
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   578
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   579
class TypeCoercionError(exceptions.ConeException):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   580
    pass
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   581
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   582
class AutoValueTerminal(Expression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   583
    PARAM_COUNT = 0
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   584
    KEY = 'autovalue_terminal'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   585
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   586
    def __init__(self, ast, expression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   587
        super(AutoValueTerminal, self).__init__(ast)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   588
        self.expression = expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   589
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   590
    def is_terminal(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   591
        return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   592
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   593
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   594
        type = kwargs.get('type', None)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   595
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   596
        if self.expression in ("None", None):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   597
            self.value = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   598
        elif type in (types.IntType, types.FloatType):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   599
            try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   600
                self.value = type(self.expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   601
            except ValueError:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   602
                raise TypeCoercionError("Cannot coerce %r to %s" % (self.expression, type))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   603
        elif type == types.BooleanType:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   604
            if self.expression in ('True', 'true', True):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   605
                self.value = True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   606
            elif self.expression in ('False', 'false', False):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   607
                self.value = False
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   608
            else:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   609
                raise TypeCoercionError("Cannot coerce %r to %s" % (self.expression, type))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   610
        elif type in types.StringTypes:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   611
            self.value = unicode(self.expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   612
        elif type == types.ListType:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   613
            self.value = list(self.expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   614
        else:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   615
            raise TypeCoercionError("Cannot coerce %r to %s" % (self.expression, type))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   616
        return self.value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   617
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   618
    def __unicode__(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   619
        return self.expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   620
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   621
    def __str__(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   622
        return self.expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   623
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   624
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   625
class NegExpression(OneParamExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   626
    PRECEDENCE = PRECEDENCES['PREFIX_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   627
    KEY= '-'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   628
    OP = ops.neg
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   629
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   630
class AndExpression(TwoOperatorBooleanExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   631
    PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   632
    KEY= 'and'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   633
    OP = truth_and
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   634
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   635
class NandExpression(TwoOperatorBooleanExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   636
    PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   637
    KEY = 'nand'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   638
    OP = nand
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   639
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   640
class OrExpression(TwoOperatorBooleanExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   641
    PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   642
    KEY = 'or'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   643
    OP = ops.or_
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   644
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   645
class XorExpression(TwoOperatorBooleanExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   646
    PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   647
    KEY = 'xor'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   648
    OP = ops.xor
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   649
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   650
class NorExpression(TwoOperatorBooleanExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   651
    PRECEDENCE = PRECEDENCES['BOOLEAN_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   652
    KEY = 'nor'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   653
    OP = nor
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   654
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   655
class EqualExpression(TwoOperatorExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   656
    PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   657
    KEY = '=='
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   658
    OP = ops.eq
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   659
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   660
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   661
        self.value = self.OP(self.left.eval(context), self.right.eval(context))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   662
        context.eval(self.ast, self, self.value)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   663
        return self.value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   664
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   665
class NotEqualExpression(TwoOperatorExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   666
    PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   667
    KEY = '!='
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   668
    OP = ops.ne
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   669
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   670
class LessThanExpression(TwoOperatorExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   671
    PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   672
    KEY = '<'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   673
    OP = ops.lt
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   674
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   675
class GreaterThanExpression(TwoOperatorExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   676
    PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   677
    KEY = '>'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   678
    OP = ops.gt
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   679
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   680
class LessThanEqualExpression(TwoOperatorExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   681
    PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   682
    KEY = '<='
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   683
    OP = ops.le
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   684
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   685
class GreaterThanEqualExpression(TwoOperatorExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   686
    PRECEDENCE = PRECEDENCES['COMPARISON_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   687
    KEY = '>='
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   688
    OP = ops.ge
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   689
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   690
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   691
def handle_multiply(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   692
    return left * right
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   693
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   694
class MultiplyExpression(TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   695
    expression = "multiply_operation"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   696
    PRECEDENCE = PRECEDENCES['MULDIV_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   697
    KEY= '*'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   698
    OP = handle_multiply
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   699
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   700
def handle_divide(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   701
    return left / right
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   702
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   703
class DivideExpression(TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   704
    expression = "divide_operation"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   705
    PRECEDENCE = PRECEDENCES['MULDIV_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   706
    KEY= '/'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   707
    OP = handle_divide
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   708
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   709
def handle_plus(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   710
    return left + right
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   711
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   712
class PlusExpression(TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   713
    expression = "plus_operation"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   714
    PRECEDENCE = PRECEDENCES['ADDSUB_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   715
    KEY= '+'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   716
    OP = handle_plus
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   717
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   718
def handle_minus(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   719
    return left - right
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   720
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   721
class MinusExpression(TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   722
    expression = "minus_operation"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   723
    PRECEDENCE = PRECEDENCES['ADDSUB_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   724
    KEY= '-'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   725
    OP = handle_minus
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   726
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   727
def handle_set(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   728
    left.set_value(right)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   729
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   730
class SetExpression(TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   731
    PRECEDENCE = PRECEDENCES['SET_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   732
    KEY= '='
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   733
    OP = handle_set
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   734
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   735
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   736
        if not isinstance(self.left, ReferenceTerminal):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   737
            raise RuntimeError("Can only set the value of a setting, '%s' is not a setting reference. Did you forget to use ${}?" % self.left.expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   738
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   739
        value = self.right.eval(context, **kwargs)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   740
        context.set(self.left.get_ref(), value, **kwargs)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   741
        return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   742
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   743
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   744
def handle_require(expression, left, right):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   745
    if left and right:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   746
        return True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   747
    elif not left:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   748
        return True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   749
    return False
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   750
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   751
class RequireExpression(TwoOperatorExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   752
    PRECEDENCE = PRECEDENCES['RELATION_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   753
    KEY = 'requires'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   754
    OP = handle_require
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   755
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   756
    def eval(self, context, **kwargs):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   757
        super(RequireExpression, self).eval(context)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   758
        if not self.value:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   759
            left_keys = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   760
            for ref in self.ast.extract_refs(unicode(self.left)):
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   761
                left_keys.append(ref)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   762
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   763
            for key in left_keys:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   764
                self.ast.add_error(key, { 'error_string' : 'REQUIRES right side value is "False"',
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   765
                                          'left_key' : key,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   766
                                          'rule' : self.ast.expression
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   767
                                          })
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   768
        return self.value
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   769
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   770
def handle_exclude(expression, left, right):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   771
    if left and not right:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   772
        return True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   773
    elif not left:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   774
        return True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   775
    return False
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   776
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   777
class ExcludeExpression(TwoOperatorExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   778
    PRECEDENCE = PRECEDENCES['RELATION_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   779
    KEY = 'excludes'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   780
    OP = handle_exclude
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   781
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   782
    def eval(self, context, **kwargs):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   783
        super(ExcludeExpression, self).eval(context)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   784
        if not self.value:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   785
            left_keys = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   786
            for ref in self.ast.extract_refs(unicode(self.left)):
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   787
                left_keys.append(ref)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   788
                    
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   789
            for key in left_keys:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   790
                self.ast.add_error(key, { 'error_string' : 'EXCLUDE right side value is "True"',
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   791
                                          'left_key' : key,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   792
                                          'rule' : self.ast.expression
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   793
                                          })
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   794
        return self.value
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   795
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   796
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   797
class NotExpression(OneParamExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   798
    PRECEDENCE = PRECEDENCES['PREFIX_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   799
    KEY = 'not'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   800
    OP = ops.not_
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   801
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   802
class TruthExpression(OneParamExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   803
    PRECEDENCE = PRECEDENCES['PREFIX_OPERATORS']
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   804
    KEY = 'truth'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   805
    OP = ops.truth
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   806
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   807
LEFT_PARENTHESIS = '('
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   808
RIGHT_PARENTHESIS = ')'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   809
class SimpleCondition(EqualExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   810
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   811
    A simple condition object that can refer to a model object and evaluate if the value matches  
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   812
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   813
    def __init__(self, left, right):
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   814
        if isinstance(left, basestring) and ASTInterpreter.is_ref(left):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   815
            lterm = ReferenceTerminal(None, left)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   816
        else:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   817
            lterm = ValueTerminal(None, left)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   818
        if isinstance(right, basestring) and ASTInterpreter.is_ref(right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   819
            rterm = ReferenceTerminal(None, right)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   820
        else:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   821
            rterm = AutoValueTerminal(None, right)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   822
        EqualExpression.__init__(self, None, lterm, rterm)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   823
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   824
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   825
        left_value = self.left.eval(context)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   826
        try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   827
            right_value = self.right.eval(context, type=type(left_value))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   828
        except TypeCoercionError:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   829
            # If type coercion fails, the result is always False
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   830
            self.value = False
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   831
            return self.value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   832
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   833
        # Type coercion successful, perform value comparison
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   834
        self.value = self.OP(left_value, right_value)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   835
        context.eval(self.ast, self, self.value)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   836
        return self.value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   837
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   838
    def get_refs(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   839
        result = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   840
        if isinstance(self.left, ReferenceTerminal):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   841
            result.append(self.left.get_ref())
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   842
        if isinstance(self.right, ReferenceTerminal):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   843
            result.append(self.right.get_ref())
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   844
        return result
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   845
    
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   846
# in format KEY : OPERATOR CLASS
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   847
OPERATORS = {
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   848
    'and' : AndExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   849
    'nand' : NandExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   850
    'or' : OrExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   851
    'xor' : XorExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   852
    'nor' : NorExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   853
    'not' : NotExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   854
    'truth' : TruthExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   855
    '==' : EqualExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   856
    '!=' : NotEqualExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   857
    '<' : LessThanExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   858
    '>' : GreaterThanExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   859
    '<=' : LessThanEqualExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   860
    '>=' : GreaterThanEqualExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   861
    'requires' : RequireExpression,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   862
    'excludes' : ExcludeExpression,
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   863
    '-' : MinusExpression,
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   864
    '+' : PlusExpression,
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   865
    '*' : MultiplyExpression,
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   866
    '/' : DivideExpression,
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   867
    '=' : SetExpression
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   868
    }
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   869
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   870
def add_operator(key, operator_class=None, baseclass=RequireExpression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   871
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   872
    Add new operator key and operator class.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   873
    If operator class isn't provided the baseclass parameter is used as
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   874
    operator base. The baseclass parameter is RequireExpression by default
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   875
    which has success condition left_rule=True and right_rule=True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   876
    
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   877
    """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   878
    OPERATORS[key] = operator_class or create_new_class(key, baseclass)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   879
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   880
def create_new_class(key, baseclass):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   881
    ns = baseclass.__dict__.copy()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   882
    ns['KEY'] = key
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   883
    key_pieces = key.split('_')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   884
    class_prefix = ''.join([key_piece.capitalize() for key_piece in key_pieces])
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   885
    new_class = type(class_prefix + 'Expression', (baseclass,), ns)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   886
    return new_class
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   887
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   888
class ParseException(Exception): pass
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   889
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   890
def is_str_literal(value):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   891
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   892
    return true if the value is a string literal. A string that begins and ends with single or douple quotes.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   893
    @param value: the value to investigate
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   894
    @return: Boolean
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   895
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   896
    if  isinstance(value, (str, unicode)):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   897
        if re.match("[\"\'].*[\"\']", value):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   898
            return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   899
    return False
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   900
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   901
def get_str_literal(value):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   902
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   903
    return the string literal value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   904
    @param value: the value to convert
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   905
    @return: string or unicode based on the input value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   906
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   907
    if  isinstance(value, (str, unicode)):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   908
        m =  re.match("[\"\'](.*)[\"\']", value)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   909
        if m:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   910
            return m.group(1)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   911
    return None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   912
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   913
class ASTInterpreter(object):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   914
    def __init__(self, infix_expression=None, context=None):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   915
        """ Takes infix expression as string """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   916
        self.context = context or DefaultContext(None)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   917
        # logger.debug("AST init context: %s" % self.context)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   918
        self._init_locals(infix_expression)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   919
        if infix_expression:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   920
            self.create_ast()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   921
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   922
    def _init_locals(self, infix_expression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   923
        # The result value of full eval of the parse_tree
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   924
        self.value = None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   925
        self.warnings = {}
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   926
        self.errors = {}
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   927
        self.postfix_array = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   928
        self.parse_tree = []
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   929
        self.expression_list = []
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   930
        self.expression = infix_expression
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   931
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   932
    def __unicode__(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   933
        s = ''
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   934
        for expr in self.parse_tree:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   935
            s += unicode(expr)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   936
        return s
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   937
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   938
    def add_error(self, key, error_dict):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   939
        if self.errors.has_key(key):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   940
            self.errors[key].append(error_dict)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   941
        else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   942
            self.errors[key] = [error_dict]
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   943
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   944
    def create_ast(self, infix_expression=None):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   945
        if infix_expression:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   946
            self._init_locals(infix_expression)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   947
        self._infix_to_postfix()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   948
        self._create_parse_tree()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   949
        return self.parse_tree
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   950
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   951
    def _infix_to_postfix(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   952
        """
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   953
        Shunting yard algorithm used to convert infix presentation to postxfix.
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   954
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   955
        if not self.expression:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   956
            raise ParseException('Expression is None')
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
   957
        tokens = get_tokens(self.expression)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   958
        stack = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   959
        # logger.debug('TOKENS: %s' % tokens)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   960
        for token in tokens:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   961
            # logger.debug('TOKEN: %s' % token)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   962
            if token.lower() in OPERATORS:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   963
                op_class = OPERATORS.get(token)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   964
                if stack:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   965
                    while len(stack) != 0:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   966
                        top = stack[-1]
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   967
                        if top in OPERATORS:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   968
                            top_operator = OPERATORS.get(top)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   969
                            if op_class.PRECEDENCE <= top_operator.PRECEDENCE:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   970
                                self.postfix_array.append(stack.pop())
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   971
                            else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   972
                                # Break from loop if top operator precedence is less.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   973
                                break
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   974
                        else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   975
                            # If top not operator break from loop
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   976
                            break
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   977
                stack.append(token)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   978
            elif token == LEFT_PARENTHESIS:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   979
                # logger.debug('Left parenthesis')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   980
                stack.append(token)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   981
            elif token == RIGHT_PARENTHESIS:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   982
                # logger.debug('Right parenthesis')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   983
                left_par_found = False
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   984
                stack_token = stack.pop()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   985
                while stack_token:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   986
                    if stack_token != LEFT_PARENTHESIS:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   987
                        self.postfix_array.append(stack_token)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   988
                    else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   989
                        left_par_found = True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   990
                        break
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   991
                    if stack:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   992
                        stack_token = stack.pop()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   993
                    else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   994
                        stack_token = None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   995
                        
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   996
                if not left_par_found:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   997
                    raise ParseException('Mismatched parenthesis "%s".' % LEFT_PARENTHESIS)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   998
            else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   999
                # logger.debug('Adding value to output. %s' % repr((token)))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1000
                self.postfix_array.append((token))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1001
            
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1002
        # There should be only operators left in the stack
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1003
        if stack:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1004
            # logger.debug('Operators in stack.')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1005
            operator = stack.pop()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1006
            while operator:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1007
                if operator != LEFT_PARENTHESIS:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1008
                    self.postfix_array.append(operator)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1009
                else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1010
                    raise ParseException('Mismatched parenthesis "%s".' % LEFT_PARENTHESIS)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1011
                if stack:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1012
                    operator = stack.pop()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1013
                else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1014
                    operator = None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1015
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1016
        # logger.debug('Infix to postfix conversion: %s' % self.postfix_array)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1017
        return self.postfix_array
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1018
    
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1019
    def _create_parse_tree(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1020
        self.parse_tree = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1021
        for token in self.postfix_array:
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1022
            is_ref = ASTInterpreter.is_ref(token)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1023
            if token in OPERATORS:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1024
                # logger.debug('OP: %s' % (token))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1025
                expression_class = OPERATORS[token]
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1026
                params = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1027
                for i in range(expression_class.PARAM_COUNT):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1028
                    try:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1029
                        params.append(self.parse_tree.pop())
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1030
                    except IndexError, e:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1031
                        raise ParseException('Syntax error: "%s"' % self.expression)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1032
                params.reverse()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1033
                expression = expression_class(self, *params)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1034
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1035
                # logger.debug('The operation: %s' % expression)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1036
                self.parse_tree.append(expression)
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1037
                self.expression_list.append(expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1038
            elif not is_ref:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1039
                expression = ValueTerminal(self, token)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1040
                self.parse_tree.append(expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1041
                self.expression_list.append(expression)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1042
            else:
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1043
                expression = ReferenceTerminal(self, token)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1044
                self.parse_tree.append(expression)
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1045
                self.expression_list.append(expression)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1046
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1047
        #logger.debug('THE STACK: %s' % self.parse_tree)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1048
        #for s in self.parse_tree:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1049
        #    logger.debug('Stack e: %s' % str(s))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1050
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1051
        return self.parse_tree
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1052
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1053
    def eval(self, context=None, **kwargs):
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1054
        """ Evals the AST
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1055
        If empty expression is given, None is returned
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1056
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1057
        for expression in self.parse_tree:
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1058
            self.value = expression.eval(context or self.context, **kwargs)
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1059
        return self.value
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1060
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1061
    @staticmethod
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1062
    def extract_refs(expression):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1063
        tokens = get_tokens(expression)
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1064
        return [ASTInterpreter.clean_ref(t) for t in tokens if t.lower() not in OPERATORS and\
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1065
                    t not in (LEFT_PARENTHESIS, RIGHT_PARENTHESIS) and\
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1066
                    ASTInterpreter.is_ref(t)]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1067
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1068
    @staticmethod
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1069
    def extract_non_operators(expression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1070
        tokens = get_tokens(expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1071
        return [ASTInterpreter.clean_ref(t) for t in tokens if t.lower() not in OPERATORS and\
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1072
                    t not in (LEFT_PARENTHESIS, RIGHT_PARENTHESIS)]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1073
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1074
    @staticmethod
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1075
    def clean_ref(ref):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1076
        return ref.replace('$', '').replace('{', '').replace('}', '')
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1077
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1078
    @staticmethod
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1079
    def create_ref(ref):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1080
        return '${%s}' % ref
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1081
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1082
    @staticmethod
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1083
    def is_ref(val):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1084
        mo = REF_REGEX.match(val)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1085
        if mo and len(mo.groups()) > 0 and mo.group() == val:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1086
            return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents: 0
diff changeset
  1087
        return False
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1088
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1089
##################################################################
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1090
# Create and configure the main level logger
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
  1091
logger = logging.getLogger('cone')