A LogicalOperation is the basic building block for a LogicalExpression. A logical operation has one or two operands and an operator. The operands can be LogicalOperation objects, fixed values or references to project data. The LogicalOperation can be evaluated in a certain context. This contexts determines the actual values of the project data references. The evaluation is done by calling LogicalOperation#eval. The result must be of a type that responds to all the operators that are used in the eval method.
Create a new LogicalOperation object. opnd1 is the mandatory operand. The @operand2 and the @operator can be set later.
# File lib/LogicalOperation.rb, line 33 33: def initialize(opnd1, operator = nil, opnd2 = nil) 34: @operand1 = opnd1 35: @operand2 = opnd2 36: @operator = operator 37: end
Evaluate the expression in a given context represented by expr of type LogicalExpression. The result must be of a type that responds to all the operators of this function.
# File lib/LogicalOperation.rb, line 42 42: def eval(expr) 43: case @operator 44: when nil 45: if @operand1.respond_to?(:eval) 46: # An operand can be a fixed value or another term. This could be a 47: # LogicalOperation, LogicalFunction or anything else that provides 48: # an appropriate eval() method. 49: return @operand1.eval(expr) 50: else 51: return @operand1 52: end 53: when '~' 54: return !coerceBoolean(@operand1.eval(expr), expr) 55: when '>', '>=', '=', '<', '<=', '!=' 56: # Evaluate the operation for all 2 operand operations that can be 57: # either interpreted as date, numbers or Strings. 58: opnd1 = @operand1.eval(expr) 59: opnd2 = @operand2.eval(expr) 60: if opnd1.is_a?(TjTime) 61: res= evalBinaryOperation(opnd1, operator, opnd2) do |o| 62: coerceTime(o, expr) 63: end 64: return res 65: elsif opnd1.is_a?(Fixnum) || opnd1.is_a?(Float) || opnd1.is_a?(Bignum) 66: return evalBinaryOperation(opnd1, operator, opnd2) do |o| 67: coerceNumber(o, expr) 68: end 69: elsif opnd1.is_a?(RichTextIntermediate) 70: return evalBinaryOperation(opnd1.to_s, operator, opnd2) do |o| 71: coerceString(o, expr) 72: end 73: elsif opnd1.is_a?(String) 74: return evalBinaryOperation(opnd1, operator, opnd2) do |o| 75: coerceString(o, expr) 76: end 77: else 78: expr.error("First operand of a binary operation must be a date, " + 79: "a number or a string: #{opnd1.class}") 80: end 81: when '&' 82: return coerceBoolean(@operand1.eval(expr), expr) && 83: coerceBoolean(@operand2.eval(expr), expr) 84: when '|' 85: return coerceBoolean(@operand1.eval(expr), expr) || 86: coerceBoolean(@operand2.eval(expr), expr) 87: else 88: expr.error("Unknown operator #{@operator} in logical expression") 89: end 90: end
Convert the operation into a textual representation.
# File lib/LogicalOperation.rb, line 93 93: def to_s(query) 94: if @operator.nil? 95: operand_to_s(@operand1, query) 96: elsif @operand2.nil? 97: @operator + operand_to_s(@operand1, query) 98: else 99: "(#{operand_to_s(@operand1, query)} #{@operator} " + 100: "#{operand_to_s(@operand2, query)})" 101: end 102: end
Force the val into a boolean value.
# File lib/LogicalOperation.rb, line 140 140: def coerceBoolean(val, expr) 141: # First the obvious ones. 142: return val if val.class == TrueClass || val.class == FalseClass 143: # An empty String means false, else true. 144: return !val.empty? if val.is_a?(String) 145: # In TJP logic 'non 0' means false. 146: return val != 0 if val.is_a?(Fixnum) || val.is_a?(Bignum) 147: 148: expr.error("Operand #{val} can't be evaluated to true or false.") 149: end
Force the val into a number. In case this fails, an exception is raised.
# File lib/LogicalOperation.rb, line 152 152: def coerceNumber(val, expr) 153: unless val.is_a?(Fixnum) || val.is_a?(Float) || val.is_a?(Bignum) 154: expr.error("Operand #{val} of type #{val.class} must be a number.") 155: end 156: val 157: end
Force the val into a String. In case this fails, an exception is raised.
# File lib/LogicalOperation.rb, line 160 160: def coerceString(val, expr) 161: unless val.respond_to?('to_s') 162: expr.error("Operand #{val} of type #{val.class} can't be converted " + 163: "into a string") 164: end 165: val 166: end
Force the val into a String. In case this fails, an exception is raised.
# File lib/LogicalOperation.rb, line 169 169: def coerceTime(val, expr) 170: unless val.is_a?(TjTime) 171: expr.error("Operand #{val} of type #{val.class} can't be converted " + 172: "into a date") 173: end 174: val 175: end
We need to do binary operator evaluation with various coerce functions. This function does the evaluation of opnd1 and opnd2 with the operation specified by operator. The operands are first coerced into the proper format by calling the block.
# File lib/LogicalOperation.rb, line 120 120: def evalBinaryOperation(opnd1, operator, opnd2) 121: case operator 122: when '>' 123: return yield(opnd1) > yield(opnd2) 124: when '>=' 125: return yield(opnd1) >= yield(opnd2) 126: when '=' 127: return yield(opnd1) == yield(opnd2) 128: when '<' 129: return yield(opnd1) < yield(opnd2) 130: when '<=' 131: return yield(opnd1) <= yield(opnd2) 132: when '!=' 133: return yield(opnd1) != yield(opnd2) 134: else 135: raise "Operator error" 136: end 137: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.