Class: Opencdd::Condition

Inherits:
Object
  • Object
show all
Defined in:
lib/opencdd/condition.rb

Defined Under Namespace

Classes: ClassReference

Constant Summary collapse

SET_PATTERN =
/\A\{(?<body>.*)\}\z/m.freeze
EXPRESSION_PATTERN =
/\A
  (?<left>[^=!<>]+?)
  \s*
  (?<op>==|!=)
  \s*
  (?<right>.+)
\z/x.freeze
SINGLE_TOKEN_PATTERN =

A single bare token (IRDI or short code) without internal whitespace. Used to detect class-reference conditions of the form 0112/2///62683#ACE132 and distinguish them from malformed input like "no operator here" (which has internal whitespace).

/\A\S+\z/.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(left, operator, right) ⇒ Condition

Returns a new instance of Condition.



24
25
26
27
28
29
30
31
# File 'lib/opencdd/condition.rb', line 24

def initialize(left, operator, right)
  @left = left.to_s.strip
  unless %w[== !=].include?(operator.to_s)
    raise ArgumentError, "unsupported condition operator: #{operator.inspect}"
  end
  @operator = operator.to_s
  @right = right
end

Instance Attribute Details

#leftObject (readonly)

Returns the value of attribute left.



22
23
24
# File 'lib/opencdd/condition.rb', line 22

def left
  @left
end

#operatorObject (readonly)

Returns the value of attribute operator.



22
23
24
# File 'lib/opencdd/condition.rb', line 22

def operator
  @operator
end

#rightObject (readonly)

Returns the value of attribute right.



22
23
24
# File 'lib/opencdd/condition.rb', line 22

def right
  @right
end

Class Method Details

.parse(raw) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/opencdd/condition.rb', line 81

def parse(raw)
  return nil if raw.nil? || raw.to_s.strip.empty?
  s = raw.to_s.strip
  if s =~ EXPRESSION_PATTERN
    left = Regexp.last_match(:left).strip
    op   = Regexp.last_match(:op)
    raw_right = Regexp.last_match(:right).strip
    new(left, op, parse_rhs(raw_right))
  elsif s =~ SET_PATTERN
    body = Regexp.last_match(:body)
    elements = body.split(/[,\s]+/).map(&:strip).reject(&:empty?)
    ClassReference.new(irdis: elements)
  elsif SINGLE_TOKEN_PATTERN.match?(s)
    ClassReference.new(irdis: [s])
  else
    raise ArgumentError, "invalid condition expression: #{s.inspect}"
  end
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



68
69
70
71
72
73
# File 'lib/opencdd/condition.rb', line 68

def ==(other)
  other.is_a?(Opencdd::Condition) &&
    @left == other.left &&
    @operator == other.operator &&
    normalize_for_eq(@right) == normalize_for_eq(other.right)
end

#class_reference?Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/opencdd/condition.rb', line 33

def class_reference?
  false
end

#hashObject



76
77
78
# File 'lib/opencdd/condition.rb', line 76

def hash
  [@left, @operator, normalize_for_eq(@right)].hash
end

#satisfied_by?(bindings) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/opencdd/condition.rb', line 41

def satisfied_by?(bindings)
  hash = bindings.is_a?(Hash) ? bindings : bindings.to_h
  actual = hash[@left] || hash[@left.to_sym]
  return false if actual.nil?

  if set?
    contained = @right.any? { |r| matches?(actual, r) }
    @operator == "==" ? contained : !contained
  else
    equal = matches?(actual, @right)
    @operator == "==" ? equal : !equal
  end
end

#set?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/opencdd/condition.rb', line 37

def set?
  @right.is_a?(Set)
end

#to_sObject Also known as: inspect



55
56
57
58
59
60
61
62
63
64
# File 'lib/opencdd/condition.rb', line 55

def to_s
  rhs = if set?
          "{ #{@right.to_a.join(", ")} }"
        elsif quoted_literal?(@right)
          "\"#{@right}\""
        else
          @right.to_s
        end
  "#{@left} #{@operator} #{rhs}"
end