# frozen_string_literal: true require_relative '../active_support/core_ext/object/to_query' require_relative 'comparator' module PageMagic # models mapping used to relate pages to uris class Mapping attr_reader :path, :parameters, :fragment # @param [Object] path String or Regular expression to match with # @param [Hash] parameters mapping of parameter name to literal or regex to match with # @param [Object] fragment String or Regular expression to match with # @raise [MatcherInvalidException] if at least one component is not specified def initialize(path = nil, parameters: {}, fragment: nil) raise MatcherInvalidException unless path || parameters || fragment @path = Comparator.for(path) @parameters = Comparator.for(parameters) @fragment = Comparator.for(fragment) end # @return [Boolean] true if no component contains a Regexp def can_compute_uri? !fragment.fuzzy? && !path.fuzzy? && !parameters.fuzzy? end # @return [String] uri represented by this mapping def compute_uri path.to_s.dup.tap do |uri| uri << "?#{parameters.comparator.to_query}" unless parameters.empty? uri << "##{fragment}" if fragment.present? end end # @return [Fixnum] hash for instance def hash [path, parameters, fragment].hash end # @param [String] uri # @return [Boolean] returns true if the uri is matched against this matcher def match?(uri) uri = URI(uri) path.match?(uri.path) && parameters.match?(parameters_hash(uri.query)) && fragment.match?(uri.fragment) end # compare this matcher against another # @param [Mapping] other # @return [Fixnum] -1 = smaller, 0 = equal to, 1 = greater than def <=>(other) path_comparison = path <=> other.path return path_comparison unless path_comparison.zero? parameter_comparison = parameters <=> other.parameters return parameter_comparison unless parameter_comparison.zero? fragment <=> other.fragment end # check equality # @param [Mapping] other # @return [Boolean] def ==(other) return false unless other.is_a?(Mapping) path == other.path && parameters == other.parameters && fragment == other.fragment end alias eql? == private def parameters_hash(string) CGI.parse(string.to_s.downcase).collect { |key, value| [key.downcase, value.first] }.to_h end end end