configurationengine/source/plugins/common/ConeLegacyRulePlugin/legacyruleplugin/relations.py
author m2lahtel
Tue, 10 Aug 2010 14:29:28 +0300
changeset 3 e7e0ae78773e
permissions -rw-r--r--
ConE 1.2.11 release
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
     1
#
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
     2
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
     3
# All rights reserved.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
     4
# This component and the accompanying materials are made available
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
     5
# under the terms of "Eclipse Public License v1.0"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
     6
# which accompanies this distribution, and is available
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
     7
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
     8
#
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
     9
# Initial Contributors:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    10
# Nokia Corporation - initial contribution.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    11
#
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    12
# Contributors:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    13
#
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    14
# Description: 
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    15
#
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    16
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    17
'''
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    18
implementation for ruleml relations.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    19
'''
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    20
import os
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    21
import StringIO
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    22
import logging
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    23
import operator as ops
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    24
import re
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    25
import sys, traceback
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    26
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    27
log = logging.getLogger('cone.ruleplugin.relations')
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    28
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    29
from legacyruleplugin import rules
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    30
from cone.public import api, utils, exceptions, plugin
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    31
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    32
class RelationFactory(api.FactoryBase):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    33
    @ classmethod
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    34
    def get_relation_by_name(cls, relation_name):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    35
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    36
        Get the class name by file extension.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    37
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    38
        try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    39
            return rules.RELATIONS.get(relation_name)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    40
        except KeyError:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    41
            raise exceptions.NotSupportedException("No Relation class found for name %s" % relation_name)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    42
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    43
    @ classmethod
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    44
    def get_relations(cls, configuration, relation):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    45
        try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    46
            relations = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    47
            (left_expression,relation_name,right_expression) = parse_rule(relation)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    48
            relation = cls.get_relation_by_name(relation_name)(configuration, left_expression, right_expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    49
            relations.append(relation)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    50
            propagated_relations = cls.get_relations(configuration, right_expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    51
            if propagated_relations:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    52
                for relation in propagated_relations:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    53
                    relations.append(relation)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    54
            return relations
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    55
        except exceptions.ParseError:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    56
            return None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    57
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    58
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    59
class ConfigurationContext(rules.DefaultContext):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    60
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    61
    def __init__(self, data):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    62
        rules.DefaultContext.__init__(self, data)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    63
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    64
        # Callback called with the setting reference when a setting is dereferenced
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    65
        # as a terminal expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    66
        self.ref_terminal_callback = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    67
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    68
        # Callback called with the setting reference when a setting is dereferenced
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    69
        # inside an EvalExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    70
        self.ref_eval_callback = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    71
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    72
        # Callback called with the setting reference when the value of a setting
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    73
        # is set inside a SetExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    74
        self.ref_set_callback = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    75
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    76
    def handle_terminal(self, expression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    77
        try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    78
            value = self.data.get_default_view().get_feature(expression).get_value()
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    79
            
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    80
            # Got a valid ref, call the callback
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    81
            if self.ref_terminal_callback:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    82
                self.ref_terminal_callback(expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    83
            
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    84
            return value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    85
        except exceptions.NotFound,e:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    86
            """ return the expression itself if it is not a fearef """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    87
            #print "handle_terminal constant %s" % (expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    88
            try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    89
                return eval(expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    90
            except (NameError,SyntaxError), e:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    91
                return expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    92
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    93
    def eval(self, ast, expression, value):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    94
        #print "expression %s = %s" % (expression,value)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    95
        pass
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    96
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    97
class ConfigurationBaseRelation(rules.BaseRelation):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    98
    def __init__(self, data, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
    99
        self.context = ConfigurationContext(data)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   100
        super(ConfigurationBaseRelation, self).__init__(data, left, right)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   101
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   102
class RequireRelation(ConfigurationBaseRelation):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   103
    KEY = 'requires'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   104
    def __init__(self, data, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   105
        super(RequireRelation, self).__init__(data, left, right)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   106
        self.context = ConfigurationContext(data)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   107
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   108
class ConfigureRelation(ConfigurationBaseRelation):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   109
    KEY = 'configures'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   110
    def __init__(self, data, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   111
        self.context = ConfigurationContext(data)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   112
        super(ConfigureRelation, self).__init__(data, left, right)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   113
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   114
        # A plugin.RelationExecutionResult object is stored here
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   115
        self._execution_result = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   116
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   117
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   118
    def execute(self, context=None):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   119
        self._execution_result = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   120
        exec_results = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   121
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   122
        result = rules.BaseRelation.execute(self, context)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   123
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   124
        if len(exec_results) > 0:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   125
            # There should be only one ConfigureExpression inside a ConfigureRelation
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   126
            if len(exec_results) > 1:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   127
                log.warning("Execution of ConfigureRelation returned more than one result, ignoring all except the first")
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   128
            self._execution_result = exec_results[0]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   129
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   130
        return result
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   131
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   132
    def get_execution_result(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   133
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   134
        Return the execution result from the most recent call to execute().
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   135
        """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   136
        return self._execution_result
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   137
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   138
def handle_configure(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   139
    if left and right:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   140
        return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   141
    elif not left:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   142
        return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   143
    return False
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   144
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   145
def handle_set(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   146
    left.set_value(right)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   147
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   148
def handle_filenamejoin(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   149
    def extract_dirname(path):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   150
        """Extract directory name (will always contain a trailing slash or backslash)"""
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   151
        pos = max(path.rfind('/'), path.rfind('\\'))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   152
        if pos == -1:   return path + '/'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   153
        else:           return path[:pos + 1]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   154
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   155
    def extract_filename(path):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   156
        pos = max(path.rfind('/'), path.rfind('\\'))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   157
        if pos == -1:   return path
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   158
        else:           return path[pos + 1:]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   159
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   160
    return extract_dirname(left) + extract_filename(right)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   161
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   162
def handle_plus(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   163
    return left + right
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   164
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   165
def handle_minus(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   166
    return left - right
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   167
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   168
def handle_multiply(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   169
    return left * right
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   170
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   171
def handle_divide(self, left, right):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   172
    return left / right
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   173
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   174
class ConfigureExpression(rules.TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   175
    PRECEDENCE = rules.PRECEDENCES['RELATION_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   176
    KEY = 'configures'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   177
    OP = handle_configure
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   178
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   179
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   180
        input_refs = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   181
        affected_refs = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   182
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   183
        # Evaluate the left-hand side expression, catching refs for the result
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   184
        try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   185
            context.ref_terminal_callback = lambda ref: input_refs.append(ref)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   186
            context.ref_eval_callback = lambda ref: input_refs.append(ref)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   187
            evaluated_left = self.left.eval(context, **kwargs)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   188
        finally:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   189
            context.ref_terminal_callback = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   190
            context.ref_eval_callback = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   191
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   192
        if evaluated_left:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   193
            # If left evaluated to True, evaluate the right-hand side and
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   194
            # catch refs from SetExpression evaluations
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   195
            try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   196
                context.ref_set_callback = lambda ref: affected_refs.append(ref)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   197
                self.value = self.right.eval(context, **kwargs)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   198
            finally:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   199
                context.ref_set_callback = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   200
        else:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   201
            self.value = True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   202
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   203
        if not self.value:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   204
            left_keys = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   205
            for ref in self.ast.extract_refs(str(self.left)):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   206
                for key in context.get_keys(ref):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   207
                    left_keys.append(key)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   208
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   209
            for key in left_keys:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   210
                self.ast.add_error(key, { 'error_string' : 'CONFIGURES right side value is "False"',
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   211
                                          'left_key' : key,
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   212
                                          'rule' : self.ast.expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   213
                                          })
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   214
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   215
        return self.value
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   216
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   217
class MultiplyExpression(rules.TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   218
    expression = "multiply_operation"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   219
    PRECEDENCE = rules.PRECEDENCES['MULDIV_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   220
    KEY= '*'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   221
    OP = handle_multiply
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   222
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   223
class DivideExpression(rules.TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   224
    expression = "divide_operation"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   225
    PRECEDENCE = rules.PRECEDENCES['MULDIV_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   226
    KEY= '/'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   227
    OP = handle_divide
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   228
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   229
class PlusExpression(rules.TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   230
    expression = "plus_operation"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   231
    PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   232
    KEY= '+'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   233
    OP = handle_plus
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   234
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   235
class MinusExpression(rules.TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   236
    expression = "minus_operation"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   237
    PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   238
    KEY= '-'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   239
    OP = handle_minus
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   240
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   241
class EvalExpression(rules.OneParamExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   242
    expression = "__eval__"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   243
    PRECEDENCE = rules.PRECEDENCES['PREFIX_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   244
    KEY = '__eval__'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   245
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   246
    def __init__(self, ast, expression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   247
        super(EvalExpression, self).__init__(ast, expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   248
        self.expression = expression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   249
        self._str_to_eval = eval(expression.expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   250
        #self.default_view = default_view
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   251
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   252
    def extract_refs(self):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   253
        result = []
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   254
        result.extend(utils.extract_delimited_tokens(self._str_to_eval, delimiters=('${', '}')))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   255
        result.extend(utils.extract_delimited_tokens(self._str_to_eval, delimiters=('@{', '}')))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   256
        return result
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   257
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   258
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   259
        # Using the configuration to pass the eval globals dictionary to here,
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   260
        # since there isn't any easy way to do this more elegantly
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   261
        globals_and_locals = {}
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   262
        if hasattr(context, '_eval_expression_globals_dict'):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   263
            globals_and_locals = context._eval_expression_globals_dict
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   264
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   265
        str_to_eval = self._str_to_eval
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   266
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   267
        def expand_feature_ref(ref, index):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   268
            var_name = "__fea_%05d" % index
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   269
            globals_and_locals[var_name] = context.configuration.get_default_view().get_feature(ref)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   270
            if context.ref_eval_callback:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   271
                context.ref_eval_callback(ref)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   272
            return var_name
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   273
        def expand_value_ref(ref, index):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   274
            var_name = "__feaval_%05d" % index
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   275
            globals_and_locals[var_name] = context.configuration.get_default_view().get_feature(ref).get_value()
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   276
            if context.ref_eval_callback:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   277
                context.ref_eval_callback(ref)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   278
            return var_name
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   279
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   280
        str_to_eval = utils.expand_delimited_tokens(str_to_eval, expand_feature_ref, delimiters=('@{', '}'))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   281
        str_to_eval = utils.expand_delimited_tokens(str_to_eval, expand_value_ref, delimiters=('${', '}'))
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   282
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   283
        # Strip leading and trailing whitespace to avoid indentation problems
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   284
        str_to_eval = str_to_eval.strip()
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   285
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   286
        ret = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   287
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   288
        try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   289
            ret = eval(str_to_eval, globals_and_locals)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   290
            return ret
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   291
        except SyntaxError, e:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   292
            logging.getLogger('cone.ruleml').warning("Invalid syntax in eval: %s" % (str_to_eval) )
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   293
            self.ast.add_error(self.expression, { 'error_string' : 'Invalid syntax in eval', 'str_to_eval' : str_to_eval, 'rule' : self.ast.expression })
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   294
        except Exception, e:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   295
            logging.getLogger('cone.ruleml').warning("Execution failed for eval: %s %s: %s" % (str_to_eval, type(e), e) )
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   296
            self.ast.add_error(self.expression, { 'error_string' : 'Execution failed for eval', 'str_to_eval' : str_to_eval, 'rule' : self.ast.expression })
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   297
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   298
rules.OPERATORS[EvalExpression.KEY] = EvalExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   299
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   300
class FilenamejoinExpression(rules.TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   301
    expression = "filenamejoin"
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   302
    PRECEDENCE = rules.PRECEDENCES['ADDSUB_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   303
    KEY = 'filenamejoin'
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   304
    OP = handle_filenamejoin
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   305
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   306
rules.OPERATORS[FilenamejoinExpression.KEY] = FilenamejoinExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   307
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   308
class SetExpression(rules.TwoOperatorExpression):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   309
    PRECEDENCE = rules.PRECEDENCES['SET_OPERATORS']
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   310
    KEY= '='
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   311
    OP = handle_set
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   312
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   313
#    def eval(self, context):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   314
#        try:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   315
#            variable = context.configuration.get_default_view().get_feature(self.left.expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   316
#            value = self.right.eval(context)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   317
#            variable.set_value(value)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   318
#            logging.getLogger('cone.ruleml').info("Set %r = %r from %r" % (self.left.expression, value, self.right.expression) )
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   319
#            if context.ref_set_callback:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   320
#                context.ref_set_callback(self.left.expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   321
#            return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   322
#        except exceptions.NotFound,e:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   323
#            self.ast.add_error(self.left.expression, { 'error_string' : 'Setting value failed, because of %s' % e,
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   324
#                               'left_key' : self.left.expression,
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   325
#                               'rule' : self.ast.expression})
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   326
#            return False
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   327
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   328
    def eval(self, context, **kwargs):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   329
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   330
        value = self.right.eval(context, **kwargs)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   331
        ref = self.left.get_ref()
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   332
        context.set(ref, value, **kwargs)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   333
        return True
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   334
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   335
_relations_and_operators_backup = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   336
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   337
def register():
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   338
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   339
    Register the relations and operators to ConE rules.
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   340
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   341
    global _relations_and_operators_backup
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   342
    if _relations_and_operators_backup is None:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   343
        # Create the backup copies of the dictionaries
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   344
        rels_backup = rules.RELATIONS.copy()
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   345
        ops_backup = rules.OPERATORS.copy()
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   346
        assert rels_backup is not rules.RELATIONS
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   347
        assert ops_backup is not rules.OPERATORS
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   348
        _relations_and_operators_backup = (rels_backup, ops_backup)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   349
        
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   350
        # Register relations and operators to rules
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   351
        rules.RELATIONS[RequireRelation.KEY] = RequireRelation
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   352
        rules.RELATIONS[ConfigureRelation.KEY] = ConfigureRelation
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   353
        rules.OPERATORS[ConfigureExpression.KEY] = ConfigureExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   354
        rules.OPERATORS[PlusExpression.KEY] = PlusExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   355
        rules.OPERATORS[SetExpression.KEY] = SetExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   356
        rules.OPERATORS[MinusExpression.KEY] = MinusExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   357
        rules.OPERATORS[MultiplyExpression.KEY] = MultiplyExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   358
        rules.OPERATORS[DivideExpression.KEY] = DivideExpression
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   359
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   360
def unregister():
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   361
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   362
    Undo the changes made by a call to register().
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   363
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   364
    global _relations_and_operators_backup
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   365
    if _relations_and_operators_backup is not None:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   366
        rules.RELATIONS = _relations_and_operators_backup[0]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   367
        rules.OPERATORS = _relations_and_operators_backup[1]
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   368
        _relations_and_operators_backup = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   369
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   370
def parse_rule(rulestring):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   371
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   372
    Divide the given rule string into (left side, relation, right side) components. 
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   373
    @return: Triple (left side, relation, right side)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   374
    """
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   375
    left_expression = ''
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   376
    relation_name = None
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   377
    right_expression = ''
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   378
    for token in rules.get_tokens(rulestring):
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   379
        if relation_name == None:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   380
            if token in rules.RELATIONS.keys():
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   381
                relation_name = token
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   382
            else:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   383
                left_expression += ' ' + token
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   384
        else:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   385
            right_expression += ' ' + token
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   386
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   387
    if relation_name == None:
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   388
        raise exceptions.ParseError('invalid rule definition %s' % rulestring)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   389
    
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   390
    return (left_expression,relation_name,right_expression)
e7e0ae78773e ConE 1.2.11 release
m2lahtel
parents:
diff changeset
   391