diff --git a/lib/floe/workflow/choice_rule/data.rb b/lib/floe/workflow/choice_rule/data.rb index 9650cf5e..e6f40797 100644 --- a/lib/floe/workflow/choice_rule/data.rb +++ b/lib/floe/workflow/choice_rule/data.rb @@ -4,59 +4,36 @@ module Floe class Workflow class ChoiceRule class Data < Floe::Workflow::ChoiceRule - COMPARE_KEYS = %w[IsNull IsPresent IsNumeric IsString IsBoolean IsTimestamp String Numeric Boolean Timestamp].freeze + COMPARE_RULE = /^(String|Numeric|Boolean|Timestamp)(Equals|GreaterThan|LessThan|GreaterThanEquals|LessThanEquals|Matches)(Path)?$/.freeze + OPERATIONS = {"Equals" => :==, "LessThan" => :<, "GreaterThan" => :>, "LessThanEquals" => :<=, "GreaterThanEquals" => :>=, "Matches" => "match?"}.freeze - attr_reader :compare_key + attr_reader :operation, :ref, :path def initialize(*) super - @compare_key = payload.keys.detect { |key| key.match?(/^(#{COMPARE_KEYS.join("|")})/) } + payload.each.detect do |key, value| + _type, operator, @path = COMPARE_RULE.match(key)&.captures + @operation = OPERATIONS[operator] + @ref = value + operator # detect aborts once an operator is found + end - raise Floe::InvalidWorkflowError, "Data-test Expression Choice Rule must have a compare key" if @compare_key.nil? + raise Floe::InvalidWorkflowError, "Data-test Expression Choice Rule must have a valid compare key" unless operation end def true?(context, input) lhs = variable_value(context, input) - rhs = compare_value(context, input) - return false unless valid?(lhs) + return false if lhs.nil? - case compare_key - when "StringEquals", "StringEqualsPath", - "NumericEquals", "NumericEqualsPath", - "BooleanEquals", "BooleanEqualsPath", - "TimestampEquals", "TimestampEqualsPath" - lhs == rhs - when "StringLessThan", "StringLessThanPath", - "NumericLessThan", "NumericLessThanPath", - "TimestampLessThan", "TimestampLessThanPath" - lhs < rhs - when "StringGreaterThan", "StringGreaterThanPath", - "NumericGreaterThan", "NumericGreaterThanPath", - "TimestampGreaterThan", "TimestampGreaterThanPath" - lhs > rhs - when "StringLessThanEquals", "StringLessThanEqualsPath", - "NumericLessThanEquals", "NumericLessThanEqualsPath", - "TimestampLessThanEquals", "TimestampLessThanEqualsPath" - lhs <= rhs - when "StringGreaterThanEquals", "StringGreaterThanEqualsPath", - "NumericGreaterThanEquals", "NumericGreaterThanEqualsPath", - "TimestampGreaterThanEquals", "TimestampGreaterThanEqualsPath" - lhs >= rhs - when "StringMatches" - lhs.match?(Regexp.escape(rhs).gsub('\*', '.*?')) - else - raise Floe::InvalidWorkflowError, "Invalid choice [#{compare_key}]" - end + rhs = compare_value(context, input) + rhs = Regexp.escape(rhs).gsub('\*', '.*?') if operation == "match?" + lhs.send(operation, rhs) end private - def valid?(value) - !value.nil? - end - def compare_value(context, input) - compare_key.end_with?("Path") ? Path.value(payload[compare_key], context, input) : payload[compare_key] + path ? Path.value(ref, context, input) : ref end end end diff --git a/spec/workflow/choice_rule_spec.rb b/spec/workflow/choice_rule_spec.rb index 2c291125..88c1903b 100644 --- a/spec/workflow/choice_rule_spec.rb +++ b/spec/workflow/choice_rule_spec.rb @@ -88,7 +88,7 @@ let(:input) { {"foo" => "bar"} } it "raises an exception" do - expect { subject }.to raise_exception(Floe::InvalidWorkflowError, "Data-test Expression Choice Rule must have a compare key") + expect { subject }.to raise_exception(Floe::InvalidWorkflowError, "Data-test Expression Choice Rule must have a valid compare key") end end