# encoding: utf-8 require "java" # this is mainly for usage with JrJackson json parsing in :raw mode which genenerates # Java::JavaUtil::ArrayList and Java::JavaUtil::LinkedHashMap native objects for speed. # these object already quacks like their Ruby equivalents Array and Hash but they will # not test for is_a?(Array) or is_a?(Hash) and we do not want to include tests for # both classes everywhere. see LogStash::JSon. class Array # enable class equivalence between Array and ArrayList # so that ArrayList will work with case o when Array ... def self.===(other) return true if other.is_a?(Java::JavaUtil::Collection) super end end class Hash # enable class equivalence between Hash and LinkedHashMap # so that LinkedHashMap will work with case o when Hash ... def self.===(other) return true if other.is_a?(Java::JavaUtil::Map) super end end # map_mixin to patch LinkedHashMap and HashMap. it must be done directly on the classes, # using a module mixin does not work, and injecting in the Map interface does not work either # but injecting in the class works. map_mixin = lambda do # this is a temporary fix to solve a bug in JRuby where classes implementing the Map interface, like LinkedHashMap # have a bug in the has_key? method that is implemented in the Enumerable module that is somehow mixed in the Map interface. # this bug makes has_key? (and all its aliases) return false for a key that has a nil value. # Only LinkedHashMap is patched here because patching the Map interface is not working. # TODO find proper fix, and submit upstream # releavant JRuby files: # https://github.com/jruby/jruby/blob/master/core/src/main/ruby/jruby/java/java_ext/java.util.rb # https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/java/proxies/MapJavaProxy.java def has_key?(key) self.containsKey(key) end alias_method :include?, :has_key? alias_method :member?, :has_key? alias_method :key?, :has_key? # Java 8 Map implements a merge method with a different signature from # the Ruby Hash#merge. see https://github.com/jruby/jruby/issues/1249 # this can be removed when fixed upstream if ENV_JAVA['java.specification.version'] >= '1.8' def merge(other) dup.merge!(other) end end end Java::JavaUtil::LinkedHashMap.module_exec(&map_mixin) Java::JavaUtil::HashMap.module_exec(&map_mixin) module java::util::Map # have Map objects like LinkedHashMap objects report is_a?(Array) == true def is_a?(clazz) return true if clazz == Hash super end end module java::util::Collection # have Collections objects like ArrayList report is_a?(Array) == true def is_a?(clazz) return true if clazz == Array super end # support the Ruby Array delete method on a Java Collection def delete(o) self.removeAll([o]) ? o : block_given? ? yield : nil end def compact duped = Java::JavaUtil::ArrayList.new(self) duped.compact! duped end def compact! size_before = self.size self.removeAll(java::util::Collections.singleton(nil)) if size_before == self.size nil else self end end # support the Ruby intersection method on Java Collection def &(other) # transform self into a LinkedHashSet to remove duplicates and preserve order as defined by the Ruby Array intersection contract duped = Java::JavaUtil::LinkedHashSet.new(self) duped.retainAll(other) duped end # support the Ruby union method on Java Collection def |(other) # transform self into a LinkedHashSet to remove duplicates and preserve order as defined by the Ruby Array union contract duped = Java::JavaUtil::LinkedHashSet.new(self) duped.addAll(other) duped end def inspect "<#{self.class.name}:#{self.hashCode} #{self.to_a(&:inspect)}>" end end