Add all Ruby Hash methods to a Java Map by "add_ruby_methods"
-------------------------------------------------------------
Key: JRUBY-4528
URL: http://jira.codehaus.org/browse/JRUBY-4528
Project: JRuby
Issue Type: Wish
Components: Java Integration
Affects Versions: JRuby 1.5
Reporter: Yoko Harada
Attachments: add_ruby_methods.patch, AddHashMethodsToMap.java
Attached patch enables to use "add_ruby_methods" method to proxied all Java Map
type objects. The new method adds all Ruby Hash methods to a Map type object.
This patch and the new method will resolve the filed bug, JRUBY-4223, and
alters my proposal, JRUBY-4314.
With this new method, we can directly manipulate Java Map objects, which is
useful especially for embedders. For example, we can use merge! method against
ConcurrentHashMap as in below:
{noformat}
ScriptingContainer container = new
ScriptingContainer(LocalContextScope.SINGLETHREAD);
ConcurrentHashMap map1 = new ConcurrentHashMap();
map1.put("a", 100);
map1.put("b", 200);
Map map2 = new HashMap();
map2.put("b", 254);
map2.put("c", 300);
container.put("h1", map1);
container.put("h2", map2);
container.put("num", 0);
String script =
"rh = h1.add_ruby_methods\n" +
"puts \"num: #{num}\"\n" +
"rh.merge!(h2.add_ruby_methods) {|k,o,n| num += 1; o+n }";
container.runScriptlet(script);
Set<Map.Entry> entries = map1.entrySet();
for (Map.Entry entry : entries) {
System.out.print(entry.getKey() + ": " + entry.getValue() + ", ");
}
{noformat}
The code produces values in ConcurrentHashMap:
{noformat}
b: 454, a: 100, c: 300,
{noformat}
Also, we can use the add_ruby_methods method on interpreter:
{noformat}
irb(main):004:0> require 'java'
=> true
irb(main):005:0> jhash = java.util.HashMap.new
=> {}
irb(main):006:0> jhash.put("1", 100)
=> nil
irb(main):007:0> jhash.put("2", 200)
=> nil
irb(main):008:0> jhash.inspect
=> "{2=200, 1=100}"
irb(main):009:0> rhash = jhash.add_ruby_methods
=> {"2"=>200, "1"=>100}
irb(main):010:0> rhash.inspect
=> "{\"2\"=>200, \"1\"=>100}"
irb(main):011:0> p rhash.values
[200, 100]
=> nil
irb(main):012:0> rhash.merge!({"2"=>222, "3"=>333})
=> {"3"=>333, "2"=>222, "1"=>100}
irb(main):013:0> jhash.inspect
=> "{3=333, 2=222, 1=100}"
{noformat}
To make this happen, I made small changes on org.jruby.RubyHash so that other
class can override some methods. Tentatively, JavaHash class is located under
org.jruby.embed.ji package, but probably, org.jruby.javasupport might be a
better place since we can also apply the method to a Java object created in
Ruby code.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email