lib/floe/workflow/choice_rule/data.rb
# frozen_string_literal: true
module Floe
class Workflow
class ChoiceRule
class Data < Floe::Workflow::ChoiceRule
def true?(context, input)
lhs = variable_value(context, input)
rhs = compare_value(context, input)
validate!(lhs)
case compare_key
when "IsNull" then is_null?(lhs)
when "IsPresent" then is_present?(lhs)
when "IsNumeric" then is_numeric?(lhs)
when "IsString" then is_string?(lhs)
when "IsBoolean" then is_boolean?(lhs)
when "IsTimestamp" then is_timestamp?(lhs)
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
end
private
def validate!(value)
raise "No such variable [#{variable}]" if value.nil? && !%w[IsNull IsPresent].include?(compare_key)
end
def is_null?(value) # rubocop:disable Naming/PredicateName
value.nil?
end
def is_present?(value) # rubocop:disable Naming/PredicateName
!value.nil?
end
def is_numeric?(value) # rubocop:disable Naming/PredicateName
value.kind_of?(Integer) || value.kind_of?(Float)
end
def is_string?(value) # rubocop:disable Naming/PredicateName
value.kind_of?(String)
end
def is_boolean?(value) # rubocop:disable Naming/PredicateName
[true, false].include?(value)
end
def is_timestamp?(value) # rubocop:disable Naming/PredicateName
require "date"
DateTime.rfc3339(value)
true
rescue TypeError, Date::Error
false
end
def compare_key
@compare_key ||= payload.keys.detect { |key| key.match?(/^(IsNull|IsPresent|IsNumeric|IsString|IsBoolean|IsTimestamp|String|Numeric|Boolean|Timestamp)/) }
end
def compare_value(context, input)
compare_key.end_with?("Path") ? Path.value(payload[compare_key], context, input) : payload[compare_key]
end
end
end
end
end