require 'saxon/s9api' module Saxon module Version # The version of the underlying Saxon library, which we need to discover at # runtime based on what version is on the Classpath class Library # The loaded version of the Saxon Java library # # @return [Saxon::Version::Library] the version of the loaded library def self.loaded_version Saxon::Loader.load! sv = Java::net.sf.saxon.Version new(sv.getProductVersion, sv.getStructuredVersionNumber, sv.softwareEdition) end include Comparable # @return [String] the version string (e.g. '9.9.1.6', '10.0') attr_reader :version # @return [String] the version components (e.g. [9, 9, 1, 6], [10, 0]) attr_reader :components # @return [Symbol] the edition (+:he+, +:pe+, or +:ee+) attr_reader :edition # @param version [String] the version string # @param components [Array] the version components separated # @param edition [String, Symbol] the name of the Saxon edition (e.g. +:he+, +'HE'+) def initialize(version, components, edition) @version = version.dup.freeze @components = components.dup.freeze @edition = edition.downcase.to_sym end # Comparison against another instance # # @param other [Saxon::Version::Library] the other version to compare against # @return [Integer] -1 for less, 1 for greater, 0 for equal def <=>(other) return false unless other.is_a?(self.class) n_components = [self.components.length, other.components.length].max (0..(n_components - 1)).reduce(0, &comparator(other)) end # Pessimistic comparison à la rubygems +~>+: do I satisfy the other # version if considered as a pessimistic version constraint # # @param pessimistic_version [Saxon::Version::Library] the version to # compare pessimistically # @return [Boolean] do I satisfy the constraint? def pessimistic_compare(pessimistic_version) pessimistic_components = pessimistic_version.components pessimistic_components = pessimistic_components + [0] if pessimistic_components.length == 1 locked = pessimistic_components[0..-2] locked = locked.zip(components[0..locked.length]) variable = [pessimistic_components[-1], components[locked.length]] locked_ok = locked.all? { |check, mine| check == mine } return false unless locked_ok check, mine = variable mine >= check end # @return [String] the version string def to_s version end private def comparator(other) ->(cmp, i) { return cmp unless cmp == 0 mine = self.components[i].nil? ? 0 : self.components[i] theirs = other.components[i].nil? ? 0 : other.components[i] mine <=> theirs } end end end end